【问题标题】:Understanding exit/reenter shared element transitions了解退出/重新进入共享元素转换
【发布时间】:2014-12-07 18:12:04
【问题描述】:

我正在对 Android L 中的共享元素转换进行一些初步探索。我设置的简单示例有一个在活动转换期间从屏幕顶部转换到屏幕底部的图像视图,我已经扩展过渡持续时间,以便我可以看到工作正常。到目前为止,我遇到了两个问题,试图了解共享元素转换是如何工作的。

1)仅使用 Enter/Return 转换时(Exit/Reenter 设置为 null)。输入过渡很好,但是当按下后退按钮时,视图会动画一段时间,停止,然后重新出现在最终位置。看起来类似于this question,但我已将所有 Exist/Reenter 转换设置为 null,所以不确定为什么会发生。

2) 仅使用 Exit/Reenter 转换时(Enter/Return 设置为 null)。什么都没有发生,视图在屏幕上向下转换,就像它遵循默认的输入转换(持续 300 毫秒)一样,当按下返回时,视图会弹回原来的位置。

如何使用退出/重新进入转换?

这是我的代码:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:src="@drawable/ic_launcher"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Animate!"
        android:id="@+id/button"
        android:layout_centerVertical="true"
        android:layout_alignParentStart="true" />

</RelativeLayout>

activity_second.xml

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/imageView2"
    android:src="@drawable/ic_launcher"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true" />

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
        getWindow().setAllowEnterTransitionOverlap(false);
        getWindow().setAllowReturnTransitionOverlap(false);


        getWindow().setSharedElementExitTransition(exitTransition());
        getWindow().setSharedElementReenterTransition(reenterTransition());
        //getWindow().setSharedElementExitTransition(null);
        //getWindow().setSharedElementReenterTransition(null);


        setContentView(R.layout.activity_main);

        final View iView = findViewById(R.id.imageView);
        iView.setTransitionName("image");

        final Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                ActivityOptions options = ActivityOptions
                        .makeSceneTransitionAnimation(MainActivity.this, iView, "image");
                startActivity(intent, options.toBundle());
            }
        });
    }

    private Transition exitTransition() {
        ChangeBounds bounds = new ChangeBounds();
        bounds.setInterpolator(new BounceInterpolator());
        bounds.setDuration(2000);

        return bounds;
    }

    private Transition reenterTransition() {
        ChangeBounds bounds = new ChangeBounds();
        bounds.setInterpolator(new OvershootInterpolator());
        bounds.setDuration(2000);

        return bounds;
    }
}

SecondActivity.java

public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
        getWindow().setAllowEnterTransitionOverlap(false);
        getWindow().setAllowReturnTransitionOverlap(false);


        //getWindow().setSharedElementEnterTransition(enterTransition());
        //getWindow().setSharedElementReturnTransition(returnTransition());
        getWindow().setSharedElementEnterTransition(null);
        getWindow().setSharedElementReturnTransition(null);


        setContentView(R.layout.activity_second);

        final View iView = findViewById(R.id.imageView2);
        iView.setTransitionName("image");
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finishAfterTransition();
    }

    private Transition enterTransition() {
        ChangeBounds bounds = new ChangeBounds();
        bounds.setDuration(2000);

        return bounds;
    }

    private Transition returnTransition() {
        ChangeBounds bounds = new ChangeBounds();
        bounds.setInterpolator(new DecelerateInterpolator());
        bounds.setDuration(2000);

        return bounds;
    }
}

【问题讨论】:

    标签: android android-5.0-lollipop shared-element-transition activity-transition


    【解决方案1】:
    1. 你不应该在onBackPressed() 中调用finishAfterTransition()Activity 超类已经为您完成了这项工作。

    2. 您应该在super.onCreate() 之前调用requestFeature()。如果您使用的是Theme.Material 主题(或类似主题),则无需请求Window.FEATURE_ACTIVITY_TRANSITIONS

    3. 在这里调用setAllowEnterTransitionOverlap(false)setAllowReturnTransitionOverlap(false) 是多余的。这些决定了 Activity 的窗口内容过渡重叠......它们根本不影响 Activity 的共享元素内容过渡。

    4. 很少需要设置退出和重新进入共享元素转换。您几乎总是希望使用 enter 和 return 转换。如果只设置了退出和重新进入共享元素的过渡,而将进入和返回共享元素的过渡保留为空,那么被调用的活动将无法知道如何在过渡开始时为共享元素设置动画,并且动画会出现中断.

    【讨论】:

    • 那么,我想使用退出/重新进入转换的场景示例是什么?编辑:我也听从了你的建议,但看起来动画回来还在打嗝。
    • 我还没有找到使用退出/重新进入转换的充分理由……事实上,它们甚至不适用于Fragment 转换。也许其他人可以对此给出一个很好的答案......
    • 嗨@AlexLockwood,你能看一下我几周前发布的关于在启用转换的情况下将活动放在活动堆栈上的问题吗?提前感谢stackoverflow.com/questions/31295598/…
    【解决方案2】:

    我记得,L 中有一个错误,如果共享元素返回转换的时间长于重新进入转换持续时间,则它会导致中断。如果您调整重新进入转换持续时间(在调用 Activity 上),那应该可以解决中断问题,直到 MR1 中的错误得到修复。

    退出和重新进入过渡用于在共享元素被允许过渡之前执行一些东西。例如,如果您想在传输共享元素之前提升它,这将在共享元素退出转换中完成。重新输入将用于做相反的事情——在视图被传回后删除视图。大多数应用不需要它,但很少有需要它的应用。

    【讨论】:

    • 我有几个后续问题。 (1) MR1 是指版本 5.0.1 还是以后的其他版本? (2) 有什么原因导致退出/重新进入共享元素转换可用于 Activity 转换但可用于 Fragment 转换?
    • (1) MR1 尚未发布。我不确定它会有什么版本。 (2) 是的!片段转换是由于某种删除(隐藏/分离/删除/替换)和某种添加(显示/附加/添加/替换)而执行的。当你执行一个 FragmentTransaction 时,你不能很好地操作 Fragment 来触发共享元素退出转换并同时移除它。
    • 仅供参考,我刚刚添加了一篇博客文章来描述这些。 halfthought.wordpress.com/2014/12/08/…
    • 酷,感谢您的帖子!顺便说一句,我也在写自己的博客文章,从this one 开始。 :)
    • @GeorgeMount 我正在使用 ActivityOptionsCompat 仍然面临同样的问题任何建议
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    相关资源
    最近更新 更多