如何在活动场景动画过渡期间阻止状态栏和导航栏动画?

rla*_*ay3 125 android android-5.0-lollipop activity-transition shared-element-transition

首先,我的状态栏背景设置为深棕色,导航栏背景为默认黑色.我正在使用Material light主题.

我正在使用ActivityOptions.makeSceneTransitionAnimation默认转换启动一个新活动,我注意到状态和导航栏都会短暂淡化为白色然后再返回正确的颜色.

根据文件:

要获得转换的完整效果,必须在调用和被调用的活动上启用窗口内容转换.否则,调用活动将开始退出转换,但随后您将看到窗口转换(如缩放或淡入淡出)

我正在使用getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);调用和被调用的活动.

同样,如果我将输入转换更改为幻灯片,状态和导航栏会短暂地具有带白色背景的幻灯片转换.

如何在活动场景动画过渡期间阻止状态栏和导航栏动画?

Ale*_*ood 212

我知道有两种方法可以防止导航/状态栏在转换过程中动画化:

方法#1:从窗口的默认退出/输入淡入淡出过渡中排除状态栏和导航栏

导航/状态栏在转换期间淡入淡出的原因是,默认情况下,一旦转换开始,所有非共享视图(包括导航/状态栏背景)将分别在您的调用/被调用的活动中淡出/淡出.但是,您可以通过从窗口的默认退出/输入Fade转换中排除导航/状态栏背景来轻松解决此问题.只需将以下代码添加到Activitys的onCreate()方法中:

Transition fade = new Fade();
fade.excludeTarget(android.R.id.statusBarBackground, true);
fade.excludeTarget(android.R.id.navigationBarBackground, true);
getWindow().setExitTransition(fade);
getWindow().setEnterTransition(fade);
Run Code Online (Sandbox Code Playgroud)

也可以使用XML(即在您自己的res/transition/window_fade.xml文件中)在活动的主题中声明此转换:

<?xml version="1.0" encoding="utf-8"?>
<fade xmlns:android="http://schemas.android.com/apk/res/android">
    <targets>
        <target android:excludeId="@android:id/statusBarBackground"/>
        <target android:excludeId="@android:id/navigationBarBackground"/>
    </targets>
</fade>
Run Code Online (Sandbox Code Playgroud)

方法#2:将状态栏和导航栏添加为共享元素

这种方法建立在klmprt的答案之上,这对我来说几乎是有用的......虽然我仍需要进行一些修改.

在我的调用Activity中,我使用以下代码启动Activity:

View statusBar = findViewById(android.R.id.statusBarBackground);
View navigationBar = findViewById(android.R.id.navigationBarBackground);

List<Pair<View, String>> pairs = new ArrayList<>();
if (statusBar != null) {
  pairs.add(Pair.create(statusBar, Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME));
}
if (navigationBar != null) {
  pairs.add(Pair.create(navigationBar, Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME));
}
pairs.add(Pair.create(mSharedElement, mSharedElement.getTransitionName()));

Bundle options = ActivityOptions.makeSceneTransitionAnimation(activity, 
        pairs.toArray(new Pair[pairs.size()])).toBundle();
startActivity(new Intent(context, NextActivity.class), options);
Run Code Online (Sandbox Code Playgroud)

到目前为止,这与klmprt在他的回答中提出的基本相同.但是,我还需要在我调用的Activity onCreate()方法中添加以下代码,以防止状态栏和导航栏在转换过程中"闪烁":

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_next);

    // Postpone the transition until the window's decor view has
    // finished its layout.
    postponeEnterTransition();

    final View decor = getWindow().getDecorView();
    decor.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            decor.getViewTreeObserver().removeOnPreDrawListener(this);
            startPostponedEnterTransition();
            return true;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

将状态栏和导航栏背景添加为共享元素将强制它们在窗口的默认退出/输入淡入淡出过渡之上绘制,这意味着它们在过渡期间不会淡出.有关此方法的更多讨论可以在此Google+信息中找到.

  • @alex这对我来说几乎是完美的,直到我们用**android.support.design.widget.TabLayout**和**android.support.design.widget.AppBarLayout**切换到新的支持库 - 现在闪烁回来了 (16认同)
  • 任何想法为什么findViewById(android.R.id.navigationBarBackground)在Lollipop上返回null?我正在使用appcompat-v7 (14认同)
  • 我正在使用android nougat在nexus 6上尝试这个解决方案.但这两种方法都不适合我. (8认同)
  • android.R.id.navigationBarBackground可以在三星或HTC设备上为您提供NPE,因为它们没有屏幕导航栏.在将它们添加为共享元素之前进行空检查 (6认同)
  • 方法#2有效,但转换发生时仍然存在闪烁(在活动中).状态栏和导航栏不再flickr. (3认同)
  • @AlexLockwood我遇到与radzio相同的问题,findViewById(android.R.id.statusBarBackground)为两个活动都返回null.我已经尝试了所有解决方案的组合,没有什么能够完全符合我的要求.然而,将工具栏和导航栏添加到过渡非常有效.只是我的观点仍在状态栏下方.有没有其他方法来获取状态栏的引用? (2认同)
  • findViewById(android.R.id.navigationBarBackground)和findViewById(android.R.id.statusBarBackground)为我返回null. (2认同)
  • 由于某些原因,方法#1对我来说不适用于牛轧糖,但方法#2确实如此!非常感谢! (2认同)