Android 以编程方式安装SystemWindows以实现状态栏透明度
我的应用程序有一个活动,为每个部分托管不同的片段。我最近将状态栏设置为半透明,将Android 以编程方式安装SystemWindows以实现状态栏透明度,android,android-layout,android-fragments,android-view,android-styles,Android,Android Layout,Android Fragments,Android View,Android Styles,我的应用程序有一个活动,为每个部分托管不同的片段。我最近将状态栏设置为半透明,将fitSystemWindows设置为true,将其设置为应用程序的背景色。对于具有工具栏的片段来说,这很好,颜色匹配,如: 然而,我的一个片段有一张照片和一个半透明的工具栏,所以我希望照片也占据状态栏的空间,而不是背景颜色 我认为解决方案是仅为该片段将fitSystemWindows设置为false,并手动向半透明工具栏添加填充。以编程方式这样做似乎没有效果,我会做错什么 以下是我的主要活动布局: <Rel
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 toolbar -->
</RelativeLayout>
这似乎没有效果,就像这样:
如果我在
主\u父视图中将fitSystemWindows
设置为false,则状态栏填充将消失,并且可以正常工作,但显然会影响每个片段看到相同的问题。通过从活动声明中删除fitSystemWindows并将paddingTop添加到片段中,在我的应用程序中解决了此问题。显然,这不是一个理想的解决方案,但似乎正在发挥作用。您可以使用协调器布局作为活动根视图,然后设置FitsSystemWindows(布尔值)
将起作用
这是因为,如本文所述,DrawerLayout
和CoordinatorLayout
在如何应用fitsystemwindows
方面都有不同的规则-它们都使用它来插入子视图,但也对每个子视图调用dispatchapplywinsets()
,允许他们访问fitsystemwindows=“true”
属性
这与布局的默认行为不同,例如FrameLayout
,当您使用fitsystemwindows=“true”
时,它会使用所有的插入,在不通知任何子视图的情况下盲目地应用填充(这是博客文章的“深度优先”部分)。我已经在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);
}
好吧,您现在处于进退两难的境地,因为一方面您需要应用插图(因为工具栏
应该正确填充),另一方面您应该不应用插图(因为您希望在状态栏下绘制图像视图
)
事实证明,框架为这种情况提供了一个很好的API:
ViewCompat.setOnApplyWindowInsetsListener(toolbar, (v, insets) -> {
((ViewGroup.MarginLayoutParams) v.getLayoutParams()).topMargin =
insets.getSystemWindowInsetTop();
return insets.consumeSystemWindowInsets();
});
假设您的根布局具有android:fitsSystemWindows=“true”
,现在适当的插入将仅应用于您的工具栏
,而不是图像视图
但是有个问题
问题是您的根布局是RelativeLayout
,它不会向其子级分派任何有关插入的信息。其同级布局也不相同(LinearLayout
,FrameLayout
)
如果您有一个“materialish”布局(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;
}
@TargetApi(Build.VERSION\u code.KITKAT\u WATCH)
@凌驾
公共窗口插页在应用窗口插页上(窗口插页插页){
int childCount=getChildCount();
for(int index=0;index
您可以查看与您的要求完全相同的详细说明
简单地说
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);
该用户问题的可能重复之处在于fitSystemWindows()
在片段事务发生后被重置,而我的问题在于我似乎无法以编程方式切换fitSystemWindows()
。仍然很相似,但这些答案都没有帮助,非常奇怪和恼人…@DanielWilson:你找到解决这个问题的方法了吗?哇,这是很久以前的事了:)我绝对建议看看-虽然现在不推荐,但它让很多这类东西“只对我有用”,我想这个方法会导致抽屉里的插图布局这一个救了我:window.decorView.requestFitSystemWindows()
getActivity().getWindow().setBackgroundDrawableResource(R.color.green);