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);