Android共享元素从初始屏幕转换为主要活动

Mon*_*sor 7 android splash-screen android-animation android-transitions shared-element-transition

在显示主要活动之前,我的应用程序显示启动画面1秒钟.启动画面和主活动共享一个公共图像,该图像是从启动画面的中心到主活动布局顶部的动画所必需的.

如果<layer-list>在主要活动中将启动画面实现为背景图像(参见启动画面正确的方式如何制作启动画面?),那么如何完成此动画并不明显,我决定实现启动画面作为正常活动,并使用共享元素转换为两个活动之间的图像设置动画.最初,我onCreate()在splash活动中使用了以下实现:

public class SplashActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);

        ImageView imageView = (ImageView)findViewById(R.id.imageView);
        String transitionName = ViewCompat.getTransitionName(imageView);
        Intent intent = new Intent(this, LoginActivity.class);
        ActivityOptionsCompat options =
                ActivityOptionsCompat.makeSceneTransitionAnimation(
                        this, imageView, transitionName);

        imageView.postDelayed(() -> {
            ActivityCompat.startActivity(SplashActivity.this, intent, options.toBundle());
            finish();
        }, 1000);
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方法存在两个问题:

  1. 在调用finish()之后立即调用startActivity()会导致在动画开始之前隐藏/销毁启动活动窗口,这导致主屏幕在动画期间暂时闪烁进入视图.
  2. 从主活动按回来会自动触发共享元素返回转换,导致主活动窗口关闭后图像在主屏幕上显示为500毫秒.返回转换失败,因为splash活动已经调用了finish(),因此不再在后台堆栈上.

为了解决第一个问题,我将finish()调用包装在postDelay()Runnable中,以确保只有在共享元素转换完成后才会调用它.在我的应用程序中有1500毫秒的延迟,但应根据其他用例所需的时间调整该值.

...

imageView.postDelayed(() -> {
    ActivityCompat.startActivity(SplashActivity.this, intent, options.toBundle());
    imageView.postDelayed(this::finish, 1500);
}, 1000);
Run Code Online (Sandbox Code Playgroud)

为了解决第二个问题,我重写了主活动的onBackPressed()方法直接调用,finish()从而避免了默认实现的调用finishAfterTransitions().这可以防止Activity尝试执行共享元素返回转换.

@Override
public void onBackPressed() {
    finish();
}
Run Code Online (Sandbox Code Playgroud)

将会理解任何替代方法或建议以改进该解决方案.

小智 0

为什么不使用共享相同活动的片段呢?我不认为有理由为如此简单的事情使用两种不同的活动。