Note that this question is very similar to the question found here. There was no resolution, so I thought I'd provide some of my code and ask again.
Essentially, I am attempting to do a shared element transition of an ImageView between two fragments. My ultimate goal is to have an animation that looks very similar to that of the default image gallery. An important point is that I'm using Glide to load my images. The issue I'm running into is that I cannot get the scaleType to animate smoothly (from centerCrop to fitCenter).
I have one fragment containing a RecyclerView whose items each contain an ImageView. These ImageViews are meant to be thumbnails, and the XML looks like this:
<ImageView
android:id="@+id/ivPhoto"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/large_spacing"
android:scaleType="centerCrop"/>
The important/problematic part being scaleType="centerCrop"
I set the transition name and load the images in my RecyclerView adapter using the following:
holder.ivPhoto.setTransitionName(current.getPhotoFilepath());
Glide.with(holder.ivPhoto.getContext())
.load(current.getPhotoFilepath())
.dontTransform()
.into(holder.ivPhoto);
When an item is clicked, the following code is run:
@Override
public void onItemClicked(AssetDetail assetDetail, ImageView imageView) {
if (assetDetail.getPhotoFilepath() != null) {
AssetDetailFragmentDirections.ActionAssetDetailFragmentToDisplayImageFragment action = AssetDetailFragmentDirections.actionAssetDetailFragmentToDisplayImageFragment(assetDetail.getPhotoFilepath());
FragmentNavigator.Extras extras = new FragmentNavigator.Extras.Builder()
.addSharedElement(imageView, assetDetail.getPhotoFilepath())
.build();
NavHostFragment.findNavController(this).navigate(action, extras);
}
}
This takes you to the second fragment, which essentially just contains the following ImageView (technically a PhotoView, I've tried with a normal ImageView too):
<com.github.chrisbanes.photoview.PhotoView
android:id="@+id/ivImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
I postpone the enter transition and set the transition I'd like to use:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
postponeEnterTransition();
TransitionSet transitionSet = new TransitionSet()
.addTransition(new ChangeBounds())
.addTransition(new ChangeImageTransform())
.setDuration(1500)
.setOrdering(TransitionSet.ORDERING_TOGETHER)
.setInterpolator(new FastOutSlowInInterpolator());
setSharedElementEnterTransition(transitionSet);
}
And finally I get & set the transition name, load the image and start the postponed enter transition:
DisplayImageFragmentArgs args = DisplayImageFragmentArgs.fromBundle(getArguments());
binding.ivImage.setTransitionName(args.getImageFilepath());
Glide.with(requireContext())
.load(args.getImageFilepath())
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
startPostponedEnterTransition();
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
startPostponedEnterTransition();
return false;
}
})
.dontTransform()
.into(binding.ivImage);
This results in this animation which is totally wrong.
If I swap the order of the transitions like this:
TransitionSet transitionSet = new TransitionSet()
.addTransition(new ChangeImageTransform())
.addTransition(new ChangeBounds())
.setDuration(1500)
.setOrdering(TransitionSet.ORDERING_TOGETHER)
.setInterpolator(new FastOutSlowInInterpolator());
I get this animation which is closer, but the enter transition starts from a strange place, and the return transition is behind/inside the CardView that holds the ImageView.
Trying with some different transitions (as per this article)
TransitionSet transitionSet = new TransitionSet()
.addTransition(new ChangeClipBounds())
.addTransition(new ChangeTransform())
.addTransition(new ChangeBounds())
.setDuration(1500)
.setOrdering(TransitionSet.ORDERING_TOGETHER)
.setInterpolator(new FastOutSlowInInterpolator());
results in this. In this one, you can see the scaleType changes instantly and then the rest of the animation happens. I want the scaleType changes to be smoothly animated with everything else.
An interesting point with the final combination of transitions is that if I remove scaleType="centerCrop"
from the ImageView in the RecyclerView it animates perfectly, but obviously this means that the images have their original aspect ratio and aren't proper thumbnails. See here.
The issue is clearly to do with the scaleType, but no matter what I try I just can't seem to get it to work. I've done a ton of Googling and reading, but found nothing that resolves the issue.
As far as I understand it, using the ChangeImageTransform is supposed to animate the scaleType, but using it with any combination of things I've tried (more than are listed here, including trying it together with ChangeTransform) doesn't seem to work, or at least not exactly how I want/expect it to. I'm beyond frustrated at this point.
If anyone could give me any assistance in resolving this I would greatly appreciate it.