Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shared element animation between RecyclerView item and CollapsingToolbar within same activity

In my application I have a list of items displayed through a RecyclerView adapter. If I click on an item a new Fragment in started within the same Activity. The layout of my item and my Activity look (simplified) like this:

Activity layout:

<android.support.design.widget.CoordinatorLayout>

    <android.support.design.widget.AppBarLayout>

        <android.support.design.widget.CollapsingToolbarLayout>

            <ImageView
                android:id="@+id/image"
                android:transitionName="image" ... />

            <android.support.v7.widget.Toolbar ... />

        </android.support.design.widget.CollapsingToolbarLayout>

        <android.support.design.widget.TabLayout ... />

    </android.support.design.widget.AppBarLayout>

    <FrameLayout... />

</android.support.design.widget.CoordinatorLayout>

Item Layout:

<RelativeLayout >

    <ImageView
        android:id="@id/itemImage"
        android:transitionName="image" />

    <LinearLayout>

        <TextView ... />

        <TextView ... />

    </LinearLayout>

</RelativeLayout>

Now, if the new fragment is started by an item click, I would like to add an animation of the item image to the ImageView in the CollapsingToolbarLayout. I read the article about ShareElement animations but this does not work here because this is not a real ShareElement animation. The target ImageView is not in the new fragment neither I have to start a new activity (I only make the target ImageView visible in the new Fragment). So how would I create such an animation in this case?

like image 408
Cilenco Avatar asked Aug 06 '17 13:08

Cilenco


1 Answers

So, you are trying to animate a view from one layout to another.

I think this can be achieved using ViewOverlays API. You can see a detailed answer about that API here.

Now in your case, what you'll end up with is you'd add your ImageView to the ViewGroupOverlay of the root layout:


    final ViewGroup container = (ViewGroup) findViewById(R.id.content);
    container.getOverlay().add(imageView);
    ...

From the docs:

If the view has a parent, the view will be removed from that parent before being added to the overlay.

Thus, as soon as you perform getOverlay().add(imageView) the view would be removed from it's parent. Now you are free to create your animation and move the imageView to the final destination.


    final ViewGroup container = (ViewGroup) findViewById(R.id.content);
    container.getOverlay().add(imageView);

    // animate imageView by any API, e.g. ViewPropertyHolder
    imageView.animate()
             .x(finalX)
             .y(finalY)
             .setDuration(duration)
             .setInterpolator(interpolator)
             .withEndAction(() -> {
                // crucial point, remove the overlay
                container.getOverlay().remove(imageView);

                // add this `imageView` to the destination layout
                destLayout.addView(imageView);
             })

Here's a similar feature you're trying to implement:

enter image description here

like image 110
azizbekian Avatar answered Oct 21 '22 14:10

azizbekian