20

I'm trying to animate 2 simple Views from a selected item in a RecyclerView to a new fragment. I've looked at a lot of examples of animating shared elements from one Activity to another Activity, but very few examples of animating a shared element from one Fragment to another Fragment within the same Activity. It almost works.

Here is my structure.

Activity

-- Full screen Fragment1 with RecyclerView

-- Full screen Fragment2 with details

When the user selects an item in the RecyclerView in Fragment1, I replace Fragment1 with Fragment2 that has a View with the shared elements in it in different positions and sizes.

There's a bit of a trick to get it to work, you have to make sure your transitionName is unique for each item in your list, and of course that transitionName must match the transitionName of the element in Fragment2 for the animation to play. I have this part working, when I select an item, the 2 shared Views do animate, just not exactly how you would expect when doing it between 2 Activities.

If I select an item near the bottom of the screen, it draws the View for Fragment2 and animates the 2 shared Views as if they were in the item at the top of the screen. Hard to explain. Here are some pictures

Fragment1 Select item near bottom of list

Fragment2 I would expect the blue line to animate from the bottom to the top, but it starts at the top and only grows horizontaly, the yellow line I would expect to stay near the bottom but grow horizontally, but it starts at the top of the screen and animates down

In both fragments I'm setting the following

        setSharedElementEnterTransition(new ChangeBounds());
        setSharedElementReturnTransition(new ChangeBounds());
        setAllowEnterTransitionOverlap(true);
        setAllowReturnTransitionOverlap(true);

Also in their parent Activity in onCreate() I've set

        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

Any idea why my shared element animations are starting at the top of my screen even when the they were starting in the selected item at the bottom of my screen?

Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
brockoli
  • 4,516
  • 7
  • 38
  • 45
  • I am not sure I understand what you are trying to achieve. I assume the weird yellow/blue bars are the views you are referring to? So in your first screenshot you click on the item and you expect the two corresponding yellow/blue bars to animate to the locations of the yellow/blue bars in the second fragment... but what happens instead? What do you mean "...it draws the View for Fragment2 and animates the 2 shared Views as if they were in the item at the top of the screen"? Also, what do the arrows in your second screenshot represent? – Alex Lockwood Nov 16 '14 at 00:05
  • BTW, if you use Android Studio, you can pretty easily take a screen capture of your application (see [**these instructions**](https://developer.android.com/sdk/installing/studio-debug.html#screenCap)) and upload it to YouTube (I know explaining the problem must be difficult). – Alex Lockwood Nov 16 '14 at 00:07
  • One last question: does this behavior _only_ happen when you select items at the bottom of the screen? For example, will it work as expected for the items at the top? – Alex Lockwood Nov 16 '14 at 00:14
  • Yes, if I select an item at the bottom of my list I expect the blue and yellow bars to start animating from the bottom of the screen. The blue one would translate up the y axis and scale down the y axis as well as scale up the x axis to finally land in it's final horizontal position at the top of the screen. Same for the yellow bar, except it wouldn't translate very far since it's already at the bottom of the screen, it would mostly just scale down the x axis and scale up the y axis to fill the bottom of the screen horizontally. I'm uploading a video to youtube now, will post when it's done – brockoli Nov 17 '14 at 15:10
  • Might be more clear to explain in terms of coordinate systems. Since Fragment 1 is a full screen RecyclerView with a bunch of items. When I click on an item and my Fragment 2 loads, it's animating as if it's using the local coordinates of the item's View instead of the parents (ReclyclerView) view. So if I select the last item, the yellow bar might start at 750,0 by it's local coordinate system, however, in the parent view, it's actually something like 750,1000 since it's at the bottom of the list. – brockoli Nov 17 '14 at 15:15
  • Here is a link to youtube (via youtubeslow to slow it down so it's more clear what is happening) http://www.youtubeslow.com/watch?v=crv71Q4G62k – brockoli Nov 17 '14 at 15:21
  • So does the bug only occur on the return transition? It looks like the enter transition from the first activity to the second works OK? – Alex Lockwood Nov 17 '14 at 15:24
  • No they are both incorrect. The shared elements should animate from the position they are in on the 1st screen to the position they are in on the 2nd screen. In this case if you watch it closely, if I select the bottom item (or any item that isn't right at the top) it always starts the animation from the top of the screen in the 2nd fragment. It start from the point on the screen where the shared element is in the 1st fragment. As you pointed out, it's also not working correctly on the return transition, for the same reasons. – brockoli Nov 17 '14 at 19:36
  • If you publish your sample project to GitHub (or something similar) I'd be happy to take a look. – Alex Lockwood Nov 20 '14 at 17:28
  • I really appreciate that. I'll put it up on bitbucket and make it public shortly. – brockoli Nov 21 '14 at 15:53
  • No problem. I've had similar issues with Activity Transitions and was able to resolve most of the problems by using `Activity#postponeEnterTransition()` and `Activity#startPostponedEnterTransition()`... but there are no equivalent methods available for `Fragment`s so I'm curious if there is a different way to solve the problem when using `Fragment` transitions... – Alex Lockwood Nov 21 '14 at 16:21
  • You can pick up my test project on bitbucket here.. https://bitbucket.org/brockoli/fragmentsharedelements – brockoli Nov 22 '14 at 00:42
  • Cool! Ill take a look this weekend – Alex Lockwood Nov 22 '14 at 16:00
  • I took a look just now with little luck... I have been able to get similar stuff working with `Activity` transitions but I haven't messed around too much with fragment transitions yet. I'll give it another shot tonight. It seems like the issue though is that fragment transition is starting before the recycler view and fragment transactions have finished... either that or the transition names aren't being set fast enough in the second fragment. – Alex Lockwood Nov 22 '14 at 20:40
  • In the mean time, you might want to continue simplifying the example until you have something that works. For example, maybe instead of sharing two elements try to make it work with only one shared element first. It's much easier to debug transitions when you start with something that works correctly and add on to that... trying to debug a more complicated example that doesn't work can be a real headache. (If that makes sense). – Alex Lockwood Nov 22 '14 at 20:51
  • I removed the blue view, so now only the orange view is being animated across fragment transition. Still not animating correctly. I cleaned up the code a bit and updated bitbucket. – brockoli Nov 24 '14 at 21:44
  • Also, I added orangeId as a member variable to my second fragment and set it before I replace/commit the fragment, so the view ID is definitly set in the new fragment before it gets replaced, so it can't be that. – brockoli Nov 24 '14 at 21:49
  • You may want to rename the R.id.container id you've defined in your item.xml file... it conflicts with the R.id.container id that you've defined for your activity's fragment container. I don't think it makes any difference as far as I can tell, but just to be safe... – Alex Lockwood Nov 25 '14 at 02:12
  • I wonder if there is something specific about RecyclerView that causes this to not work properly. For example, questions that come to mind are: does it work without a recycler view? Does it work with a normal list view? Hmm... – Alex Lockwood Nov 25 '14 at 16:25
  • I tried using a ListView tonight instead of RecyclerView. Same behavior. As far as I can tell, this just doesn't work in the same way as shared elements between Activities. I'm pretty much at a loss. – brockoli Nov 27 '14 at 00:58

1 Answers1

38

Finally solved this problem! As it turns out because the view I'm sharing between 2 fragments is a child of another view (RelativeLayout) in the 2nd fragment, you need to add the ChangeTransform transition to your TransitionSet. Apparently ChangeTransform tells the system to remember the views original position in the 1st fragment before animating to the new position in the 2nd fragment. Here is my updated transitionSet. I'll also clean up my test project code a bit and make a final push to bitbucket in case it will help others after me. Thanks for all the help with this one Alex and thank you to @George-mount for answering someones similar question that dropped the hint to me for this solution.

<?xml version="1.0" encoding="utf-8"?>

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

https://bitbucket.org/brockoli/fragmentsharedelements

brockoli
  • 4,516
  • 7
  • 38
  • 45
  • Huh... wow. Glad you finally figured it out. Definitely wasn't expecting that to be the solution. :) – Alex Lockwood Dec 27 '14 at 16:44
  • Thanks a lot! Does it need for fragments to have one frameLayout? I have been confused about "As it turns out because the view I'm sharing between 2 fragments is a child of another view (RelativeLayout) in the 2nd fragment," – busylee Jun 10 '15 at 13:16
  • @brockoli, I'm trying the same thing - just that the two fragments are in different activities. And your code doesn't work in that case. Would you know what to do in that case? – Anand Sainath Jan 09 '16 at 00:12
  • https://stackoverflow.com/questions/53179476/fragment-to-fragment-animation-with-shared-element-dont-work-as-expected – Phantom Lord Nov 14 '18 at 12:10