I have a number of shared elements that I'm transitioning between two activities via ActivityOptions.makeSceneTransitionAnimation
. When I enter the second activity, I would like to determine what the final target size that the ImageView
will be so I can set the appropriate width of the ImageView
. I believe that doing so will allow the object to the right of it (also a shared element) to transition smoothly.
The ImageView
is a fitStart
scaleType with a fixed height and a wrap_content
width. The image will be dynamically loaded and is being shrunk down from the first activity to the second, so I don't know the final width. Before the transition starts, I want to set the ImageView
's LayoutParams
width to match the final width that it will be after the transition ends.
Currently, the wrap_content
property of this ImageView
is causing the element to the right of it to not know where its final resting place will be, so it goes off the screen to the right before coming back in and landing in the right place.
Here's a gif of the animation. FIRST ELEMENT is the ImageView
, animating correctly, and Second Element is the button to the right of the ImageView
:
Notice that when the second activity goes back to the first activity, the Second Element transitions smoothly back to the left of the screen because the end position is known.
When I give the ImageView
a specific width like 100dp
instead of wrap_content
(and then change it back to wrap_content
after the transition finishes), Second Element moves more smoothly to its final resting place, but since the ImageView
will be dynamically loaded and scaled, I won't know the true width of the image in XML beforehand so there would always be a jerky movement of the Second Element when I change it to wrap_content
after the transition.
So I would like to determine the target width of the ImageView
and set it programmatically before the transitions begin in the second activity so that Second Element knows how far to the left it needs to go. I've tried playing with ViewTreeObserver
and TransitionValues
but am missing how to get the final width the ImageView is transitioning to.
Is there something I can call in onCreate
of the second activity to determine what width the ImageView will end up at after the transition?
EDIT
I tried the solution in this answer but it's reporting back the ImageView's beginning width, not the final width it's transitioning to. For reference, these are the layouts of the two activities I'm switching between:
Note that I'm moving AND shrinking the ImageView.
I tweaked the answer's code since I'm not using the support library and had to move to imageView.getViewTreeObserver()
in the onPreDraw()
call to avoid an IllegalStateException
:
postponeEnterTransition();
final ImageView imageView = (ImageView) findViewById(R.id.image_view);
final ViewGroup.LayoutParams imageViewLayoutParams = imageView.getLayoutParams();
final ViewTreeObserver viewTreeObserver = imageView.getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override public boolean onPreDraw() {
imageView.getViewTreeObserver().removeOnPreDrawListener(this);
// You can acquire the width here
logoLayoutParams.width = imageView.getWidth();
Log.i(TAG, "width is " + imageViewLayoutParams.width);
imageView.setLayoutParams(imageViewLayoutParams);
// `imageView` has been laid out, but not yet been drawn
startPostponedEnterTransition();
return true;
}
});
The log is reporting a width of 998, which is the larger size of the imageView in Activity 1 (its starting size before the transition). So the Second Element is still flying off the screen.
Now that I have this code in place, I can use the aspect ratio information of the larger image to figure out the final width that the smaller image will be since I know the final height, but is that guaranteed with the fitStart
scaleType?
It would be really nice to know if Android can tell me the final size the shared element targeting.
Here's the case: if you change in the second activity the resource from @drawable/first_element
to @drawable/first_element_thumb
, you'll no long experience that behavior. The downside is, that you'll see a glitch each time the transition is starting, that's because the drawable is being changed from high resolution to a low resolution right before transition starts.
Here's with 300ms animation time:
Here's with 5000ms animation time:
If you want the transitioning to be without that glitch, than the solution is to start the transition from high resolution drawable and substitute that drawable to a low resolution whilst transitioning the view. You can see Nick Butcher describing the feature in his "Animatable" talk. You'll end up writing your custom transition class like this one.