我的应用有一个活动,每个部分都有不同的片段。我最近将状态栏设置为半透明,方法是将fitSystemWindows
设置为true
,将其设置为应用的背景颜色。这适用于具有工具栏的片段,颜色匹配,如下所示:
然而我的一个片段有一张照片和一个半透明的工具栏,所以我想让照片占据状态栏的空间,而不是背景颜色。
我认为解决方案是仅为该片段设置fitSystemWindows
到false
,并手动将填充添加到半透明工具栏。以编程方式执行此操作似乎没有任何效果,我可能做错了什么?
这是我的主要活动布局:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_parent_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true">
<!-- Container for various fragment layouts, including nav drawer and tool bar -->
</RelativeLayout>
从我的片段中的onCreateView():
RelativeLayout daddyLayout = (RelativeLayout)getActivity().findViewById(R.id.main_parent_view);
daddyLayout.setFitsSystemWindows(false);
daddyLayout.invalidate();
这似乎没有效果,如下:
如果我在fitSystemWindows
中将main_parent_view
设置为false,则状态栏填充消失并且有效,但显然会影响每个片段。
答案 0 :(得分:11)
那么,你处于两难境地,因为一方面你需要应用插图(因为Toolbar
应该正确填充),另一方面你应该不适用插图(因为您希望在状态栏下绘制ImageView
)。
事实证明,框架为这种情况提供了一个很好的API:
ViewCompat.setOnApplyWindowInsetsListener(toolbar, (v, insets) -> {
((ViewGroup.MarginLayoutParams) v.getLayoutParams()).topMargin =
insets.getSystemWindowInsetTop();
return insets.consumeSystemWindowInsets();
});
假设您的根布局有android:fitsSystemWindows="true"
,现在适当的插图将仅应用于Toolbar
,而不是ImageView
。
但是,这是一个问题。
问题是您的根布局是RelativeLayout
,它不会向其子级发送有关插入的任何信息。它的兄弟布局(LinearLayout
,FrameLayout
)也没有。
如果您拥有&#34;物质化的&#34;布局(CoordinatorLayout
,DrawerLayout
),然后将子项发送给那些窗口插件。
另一个选项是子类RelativeLayout
并发送WindowInsets
孩子们手动。
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
int childCount = getChildCount();
for (int index = 0; index < childCount; index++)
getChildAt(index).dispatchApplyWindowInsets(insets); // let children know about WindowInsets
return insets;
}
您可以看到this answer的详细说明,但要求与您完全相同。
答案 1 :(得分:7)
我已在4.4
中解决了这个问题if(test){
Log.d(TAG, "fit true ");
relativeLayout.setFitsSystemWindows(true);
relativeLayout.requestFitSystemWindows();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}else {
Log.d(TAG, "fit false");
relativeLayout.setFitsSystemWindows(false);
relativeLayout.requestFitSystemWindows();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
答案 2 :(得分:4)
看到同样的问题。通过从活动声明中删除fitSystemWindows并将paddingTop添加到片段,解决了我在我的应用程序中的问题。显然不是一个理想的解决方案,但似乎有效。
答案 3 :(得分:4)
您可以使用Z
作为活动根视图,然后CoordinatorLayout
即可使用。
这是因为,正如blog post中所述,setFitsSystemWindows(boolean)
和DrawerLayout
对CoordinatorLayout
如何适用于他们有不同的规则 - 他们都使用它来插入他们的子视图,但也为每个孩子调用fitsSystemWindows
,允许他们访问dispatchApplyWindowInsets()
属性。
这与布局(例如fitsSystemWindows="true"
)的默认行为有所不同,其中当您使用FrameLayout
时会消耗所有插图,盲目地应用填充而不通知任何子视图(这是'深度优先'部分博客文章)。
答案 4 :(得分:0)
简单地放置
View decorView = getActivity().getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
和状态栏颜色使用:
getActivity().getWindow().setBackgroundDrawableResource(R.color.green);