Android 三个片段之间的过渡共享元素

Android transition shared element between three fragments

我正在尝试使用共享元素在片段之间实现一些不错的转换,这是我想要实现的:

当我从 片段 1 切换到 片段 2 时:

当我从 片段 2 切换到 片段 3 时:

这是 片段 1 的设置:

Fagment1.java:

fragment.setExitTransition("fade"); //parameter shortened for readability

XML:

<ImageView [...]
    android:id="@+id/octopuss"
    android:transitionName="@string/octopuss"/>

这是 片段 2 的设置:

Fragment2.java:

fragment3.setEnterTransition("slide_bottom");
fragment3.setSharedElementEnterTransition("move");
fragment3.setExitTransition("fade");

XML:

<ImageView [...]
    android:transitionName="@string/octopuss"/>

<TextView [...]
    android:transitionName="title1"
    android:id="@+id/title1" />

在 Activity 中调用片段 2:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction()
    .replace(R.id.fullscreen_content, fragment2)
    .addToBackStack("connection_transaction");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)     
    ft.addSharedElement(findViewById(R.id.octopuss), getString(R.string.octopuss));
ft.commit();

这是 片段 3 的设置:

Fragment3.java:

fragment3.setEnterTransition("slide_bottom");
fragment3.setSharedElementEnterTransition("slide_right");

XML:

<ImageView [...]
    android:transitionName="@string/octopuss"/>

<TextView [...]
    android:transitionName="title1"/>

在 Activity 中征集碎片兵 3:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction()
    .replace(R.id.fullscreen_content, fragment3)
    .addToBackStack("preferences_transaction");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    ft.addSharedElement(findViewById(R.id.title1), "title1");
ft.commit();

片段 1片段 2 之间的每个过渡效果都很好。

但是当我调用 片段 3 时,每个片段开始它的 enterTransition\exitTansition 就像它们根本没有共享元素一样:

谁能帮我找出原因?我缺少什么?

这变成了一个有点冗长的答案:解释为什么它不起作用以及如何让它起作用。

问题

我认为这里对于共享元素的构成及其工作方式存在一些混淆。

请记住,基本思想是您正在从一个屏幕(activity 或片段)移动到另一个屏幕,共享元素表示同时出现在两个屏幕上的内容。为了连续性和更平滑的过渡,您希望该项目从它在第一个屏幕上的位置平滑地更改到第二个屏幕上的位置。

共享元素不是只是一个在过渡期间独立于布局的其余部分移动的项目。

话虽如此;在此示例中,中央大徽标变为角落小徽标的第一个过渡是共享元素过渡的一个很好的示例。

第二个并不是真正的共享元素转换。 我不确定 fragment3.setSharedElementEnterTransition("slide_right"); 行包含什么(我想你为了清楚起见将它缩写了)但我怀疑当你的应用程序 运行ning 时它被忽略了,因为它不是有效的共享元素转换。

将共享元素告诉 "slide right" 没有意义,因为根据定义,元素移动的方向取决于其对应元素的位置;它会那里移动,无论哪个方向。

Title 1 和 Title 2 之间的实际共享元素过渡看起来一点也不像,因为它们在同一位置大小相同,所以它们只会停留在那里。

万事俱备

使用共享元素转换完成这项工作的方法是将标题 1 和标题 2 放在 both 片段中并添加 two共享元素。在一个片段中,标题 1 将位于正常位置,而标题 2 将隐藏在屏幕的 right-hand 一侧。在另一个中,标题 2 将位于正常位置,而标题 1 将隐藏在屏幕左侧。

对于您的 off-screen TextView,请使用 android:translationX="-86dp"(或其他数字将其定位在屏幕左侧或右侧)。

注意事项:您不会在布局预览中看到 translationX 属性的效果,只有当您 运行 应用程序时才会看到。

确保为 title1 和 title2 匹配适当的 transitionNames。