Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shared element transitions not working when combined with a CoordinatorLayout and CollapsingToolbarLayout

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.

like image 608
Monte Creasor Avatar asked Oct 11 '15 07:10

Monte Creasor


1 Answers

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.

like image 198
Monte Creasor Avatar answered Jan 05 '23 03:01

Monte Creasor