当活动从一个切换到另一个时,共享元素会在新的活动中覆盖导航栏,如图片所示。
您还可以在视频中看到此错误:查看覆盖导航栏
当活动从一个切换到另一个时,共享元素会在新的活动中覆盖导航栏,如图片所示。
您还可以在视频中看到此错误:查看覆盖导航栏
(1) 在您的XML中设置
android:windowSharedElementsUseOverlay="false"
以禁用覆盖层。禁用后,共享元素将作为被调用Activity的视图层次结构的一部分绘制,这使得共享元素不可能意外地重叠在系统UI栏的顶部。
不幸的是,禁用此行为可能会引入新问题...
例如,您可能会发现在任一Activity中的非共享视图在过渡到其位置时会剪切共享元素。在大多数情况下,您可以通过在XML中为每个共享元素的父级设置android:cliptoChildren="false"
和"android:clipToPadding="false"
来防止这种情况发生,但根据具体用例可能需要进行其他配置。
(2) 将操作栏、状态栏背景和导航栏背景添加为额外的共享元素
通过将系统栏设为共享元素,您可以确保原始共享元素和系统UI在窗口的View层次结构顶部以相同的级别绘制。要获取对这些视图的引用,可以使用以下代码:
View decor = getWindow().getDecorView();
View statusBar = decor.findViewById(android.R.id.statusBarBackground);
View navBar = decor.findViewById(android.R.id.navigationBarBackground);
View actionBar = decor.findViewById(getResources().getIdentifier("action_bar_container", "id", "android"));
您可以参考此帖子了解更多讨论。
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
在活动的主题中。
但它需要设置状态栏的颜色,所以我不能将其设置为false。否则,可以通过运行时设置此标志。
if (Build.VERSION.SDK_INT >= 21) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
}
Window
的clearFlags
方法清除此标志。然后,在第二个活动中开始转换动画之前清除此标志,并在转换完成后添加此标志。这只需要在被调用的活动中执行。
更新
我找到了更好的解决方案。在Android中,每个共享元素视图都在装饰视图的顶部绘制。导航栏背景通常位于装饰视图的顶部。但在转换时间内,共享元素会更高地排列。navigationBarBackground
视图添加到共享元素中,从而可以从getWindow().getDecorView().findViewById(android.R.id.navigationBarBackground)
访问它。为此,您需要将其添加到调用活动中的共享元素中,并将其添加到被调用活动中的共享元素中。onCreate()
方法中解决此问题的示例。ActivityCompat.postponeEnterTransition(this);
final View decorView = getWindow().getDecorView();
decorView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
decorView.removeOnLayoutChangeListener(this);
View navigationBarBackground = getWindow().getDecorView().findViewById(android.R.id.navigationBarBackground);
if (navigationBarBackground != null) {
android.support.v4.view.ViewCompat.setTransitionName(navigationBarBackground, "navigationBg");
}
ActivityCompat.startPostponedEnterTransition(MyActivity.this);
}
});
Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME
和 Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME
作为转换名称。 - kuelyeWindow.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME
作为transitionName,甚至不需要使用setTransitionName。实际上,在onLayoutChange中调用ActivityCompat.startPostponedEnterTransition(MyActivity.this);
就足够了。 - alexbchrgetWindow().setEnterTransition(null);
这也将解决共享元素位于状态栏后面且在启动动画时出现故障的问题。