My application main screen contains a grid view of images. When the user selects an image, a detail activity is started using a shared element transition that animates the selected grid image to a paired image located in a CardView in the detail activity.
After upgrading my detail view XML layout to include a CoordinatorLayout along with a CollapsingToolbarLayout, the shared element transition moves the image view to the wrong location in the detail activity (the "enter" activity). The framework seems to ingore the offset of the entire AppBarLayout and inner CollapsingToobarLayout and animates to the approximate position the image would be if there were no CollapsingToolBarLayout above the CardView that contains the target image view.
The problem can be duplicated in Chris Banes' cheesesquare sample app by adding an ImageView (with a transitionName) to any one of the 3 CardViews in activity_detail.xml:
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"
android:transitionName="sharedImage" />
and then setup a shared element transition in onBindViewHolder in CheeseListFragment.java as follows:
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mBoundString = mValues.get(position);
holder.mTextView.setText(mValues.get(position));
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Context context = v.getContext();
Intent intent = new Intent(context, CheeseDetailActivity.class);
intent.putExtra(CheeseDetailActivity.EXTRA_NAME, holder.mBoundString);
holder.mImageView.setTransitionName("sharedImage");
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(
getActivity(v.getContext()),
holder.mImageView,
"sharedImage");
ActivityCompat.StartActivity((MyActivity) context, intent, options.toBundle());
}
});
Glide.with(holder.mImageView.getContext())
.load(Cheeses.getRandomCheeseDrawable())
.fitCenter()
.into(holder.mImageView);
}
If you run the application, and click on a cheese list item, you will how the transition animation moves the image to an incorrect (too high) offset in the destination activity view. Once the animation completes the image will appear to "warp" into the correct position.
Any thoughts on possible work-arounds would be very welcome.
The answer is simple, cheesesquare activity_detail.xml layout, in brief, looks like this...
<android.support.design.widget.CoordinatorLayout
android:fitsSystemWindows="true"
...>
<android.support.design.widget.AppBarLayout
android:fitsSystemWindows="true"
...>
<android.support.design.widget.CollapsingToolbarLayout
android:fitsSystemWindows="true"
...>
<ImageView
android:fitsSystemWindows="true"
... />
<android.support.v7.widget.Toolbar
... />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
app:layout_behaviour="@string/appbar_scrolling_view_behaviour"
...>
</android.support.design.widget.CoordinatorLayout>
What is wrong with this layout is that the android:fitsSystemWindows property needs to be propagated down the layout chain to ALL containers, and in the published demo app, this property is missing for the NestedScrollView. Modifying the NestedScrollView to
<android.support.v4.widget.NestedScrollView
app:layout_behaviour="@string/appbar_scrolling_view_behaviour"
android:fitsSystemWindows="true"
...>
fixes the problem. This should probably be changed in the demo Github code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With