Alex Ionescu Alex Ionescu - 2 months ago 41
Android Question

Android shared element transition bug

As you can see in this video, I am trying to animate the open of a new activity. The images are animated properly when opening the activity, but fail miserably when going back (I'm using

supportFinishAfterTransition()
)

I've tried all sorts of methods that I've found here or on Google, but nothing worked, i.e.:

Defining a transition under the res/transition:

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeBounds/>
<changeImageTransform/>
</transitionSet>


and then use it in both the styles of the main activity and the one that I'm opening:

<!-- enable window content transitions -->
<item name="android:windowActivityTransitions">true</item>
<!-- specify shared element transitions -->
<item name="android:windowSharedElementEnterTransition">
@transition/change_image_transform</item>
<item name="android:windowSharedElementExitTransition">
@transition/change_image_transform</item>


I've also tried the same in my java code:

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().setSharedElementExitTransition(...);
getWindow().setSharedElementEnterTransition(...);


From my view holder I'm starting the new activity by doing so:

private void openNewActivity() {
String transitionName = "details";

Intent intent = new Intent(mContext, ActivityCardDetails.class);

ViewCompat.setTransitionName(mImageView, transitionName);

//noinspection unchecked
ActivityOptionsCompat options =
ActivityOptionsCompat.makeSceneTransitionAnimation((MainActivity)mContext,
mImageView, // The view which starts the transition
transitionName // The transitionName of the view we’re transitioning to
);


ActivityCompat.startActivity((MainActivity) mContext, intent, options.toBundle());
}


This is the ImageView that starts the animation:

<ImageView
android:layout_width="match_parent"
android:layout_height="180dp"
android:id="@+id/business_card_image"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />


and this is the second ImageView that should animate it back:

<ImageView
android:id="@+id/business_card_image"
android:layout_width="match_parent"
android:layout_height="180dp"
android:scaleType="centerCrop"
android:fitsSystemWindows="@bool/isFitSystemWindows"
android:transitionName="@string/transition_card_details"
app:layout_collapseMode="parallax" />


PS: I'm using Glide to load the images as this is user created content and I have no control over the aspect ratio of the images.

Glide.with(mContext)
.load(toLoad)
.fitCenter()
.centerCrop()
.crossFade()
.into(mImageView);


I've been struggling with this issue for weeks now and I just can't seem to overcome it.

Why can't it animate its bounds back?

Thank you!

UPDATE: Apparently the bug is related to the image width. If I'm setting the width to a constant (say 200dp) the animation runs just fine in both ways, but if I'm setting the image width to
match_parent
the return animation is broken.

UPDATE2: I can pretty much say that this bug is related to the image loading lib (Glide or Picasso both have this issue)

Answer

Apparently the issue has been described before here and here. The issue comes indeed from the image loader.

The trick was to use .dontTransform() with

ActivityCompat.postponeEnterTransition(this)
ActivityCompat.startPostponedEnterTransition(ActivityCardDetails.this)

to only play the animation when the image is properly loaded.