RecyclerView 项目和 CollapsingToolbar 之间的共享元素动画 activity

Shared element animation between RecyclerView item and CollapsingToolbar within same activity

在我的应用程序中,我有一个通过 RecyclerView 适配器显示的项目列表。如果我单击一个项目,则会在相同的 Activity 中启动一个新的 Fragment。我的项目布局和我的 Activity 外观(简化)如下:

Activity布局:

<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>

项目布局:

<RelativeLayout >

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

    <LinearLayout>

        <TextView ... />

        <TextView ... />

    </LinearLayout>

</RelativeLayout>

现在,如果新片段是通过单击项目启动的,我想将项目图像的动画添加到 CollapsingToolbarLayout 中的 ImageView。我阅读了 the article 有关 ShareElement 动画的内容,但这在这里不起作用,因为这不是真正的 ShareElement 动画。目标 ImageView 不在新片段中,我也不必开始新的 activity(我只使目标 ImageView 在新的 Fragment 中可见)。那么在这种情况下我该如何创建这样的动画呢?

因此,您正在尝试将视图从一种布局动画化到另一种布局。

我认为这可以使用 ViewOverlays API 来实现。您可以看到有关 API .

的详细答案

现在在你的情况下,你最终会得到的是你将 ImageView 添加到根布局的 ViewGroupOverlay 中:


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

来自docs

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

因此,一旦您执行 getOverlay().add(imageView) 视图就会从其父视图中删除。现在您可以自由地创建动画并将 imageView 移动到最终目的地。


    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 您正在尝试实现的类似功能: