13

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.

Sdghasemi
  • 5,370
  • 1
  • 34
  • 42
Monte Creasor
  • 466
  • 5
  • 12

2 Answers2

2

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.

Monte Creasor
  • 466
  • 5
  • 12
  • I still get a flicker with the navigation bar and status bar when i have a layout similar to the cheesesquare detail screen layout. How do you fix this for a shared element transition? – Etienne Lawlor Apr 27 '16 at 03:05
  • The answer can be found in this post. http://stackoverflow.com/questions/26600263/how-do-i-prevent-the-status-bar-and-navigation-bar-from-animating-during-an-acti – Monte Creasor Apr 30 '16 at 00:20
-1

Solved!

If anybody is facing this error in which they are using coordinator layout which consist shared elements, which during shared element transition from previous activity to the activity which contains coordinator layout, gets placed wrongly during the transition animation. This is a bug in the design support library version "com.android.support:design:22.2.0"

Solution:

Change the version to "com.android.support:design:23.1.0" in build.gradle(app)

Everything shall work perfect as intended. This worked out for me, found this solution after a lot of research.

Udit Kapahi
  • 2,277
  • 1
  • 27
  • 25
  • Sorry Udit, but your solution does not solve the issue. I just tested it with design:23.1.1 and it still shows up. Just go to your phone's developer options and slow down your animations by 5x and you will be able to see the warping. My test was on Nexus 6 API 22 (emulator). Adding the fitSystemWindows attribute to the NestedScrollView fixes the problem as I already mentioned below. – Monte Creasor Mar 24 '16 at 21:22
  • Still getting the problem with design 23.3.0 :( any solution? – Sdghasemi Jul 23 '16 at 02:14