fitSystemWindows 以编程方式实现状态栏透明度
fitSystemWindows programmatically for status bar transparency
我的应用程序有一个 activity 为每个部分托管不同的片段。我最近通过将 fitSystemWindows
设置为 true
将状态栏设置为半透明,这已将其设置为应用程序的背景颜色。这对于具有工具栏的片段来说很好,颜色匹配,如下所示:
但是我的一个片段有照片和半透明的工具栏,所以我想让照片也占据状态栏的 space,而不是背景颜色。
我认为解决方案是仅针对该片段将 fitSystemWindows
设置为 false
,然后手动向半透明工具栏添加填充。以编程方式执行此操作似乎没有效果,我做错了什么?
这是我的主要 activity 布局:
<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>
然后从我片段的 onCreateView() 中:
RelativeLayout daddyLayout = (RelativeLayout)getActivity().findViewById(R.id.main_parent_view);
daddyLayout.setFitsSystemWindows(false);
daddyLayout.invalidate();
这个好像没有效果,像这样:
如果我在 main_parent_view
中将 fitSystemWindows
设置为 false,状态栏填充将消失并且有效,但显然 影响每个片段 。
看到了同样的问题。通过从 activity 声明中删除 fitSystemWindows 并将 paddingTop 添加到片段中,在我的应用程序中解决了这个问题。显然不是一个理想的解决方案,但似乎有效。
您可以使用 CoordinatorLayout
作为您的 activity 根视图,然后 setFitsSystemWindows(boolean)
将起作用。
这是因为,如本 blog post 中所述,DrawerLayout
和 CoordinatorLayout
对于 fitsSystemWindows
如何应用于它们都有不同的规则 - 它们都使用它来插入他们的 child 视图,但也在每个 child 上调用 dispatchApplyWindowInsets()
,允许他们访问 fitsSystemWindows="true"
属性.
这与 FrameLayout
等布局的默认行为不同,其中当您使用 fitsSystemWindows="true"
时会消耗所有插图,盲目应用填充而不通知任何 child 视图(即博客的 'depth first' 部分 post).
我已经在 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);
}
好吧,你在那里处于两难境地,因为一方面你需要应用插图(因为 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
)。
如果您有 "materialish" 布局(CoordinatorLayout
、DrawerLayout
)之一作为根布局,那么子级将被分派那些 window 插图。
另一种选择是继承 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;
}
您可以查看 以获得与您完全相同的要求的详细说明。
简单地说
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);
我的应用程序有一个 activity 为每个部分托管不同的片段。我最近通过将 fitSystemWindows
设置为 true
将状态栏设置为半透明,这已将其设置为应用程序的背景颜色。这对于具有工具栏的片段来说很好,颜色匹配,如下所示:
但是我的一个片段有照片和半透明的工具栏,所以我想让照片也占据状态栏的 space,而不是背景颜色。
我认为解决方案是仅针对该片段将 fitSystemWindows
设置为 false
,然后手动向半透明工具栏添加填充。以编程方式执行此操作似乎没有效果,我做错了什么?
这是我的主要 activity 布局:
<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>
然后从我片段的 onCreateView() 中:
RelativeLayout daddyLayout = (RelativeLayout)getActivity().findViewById(R.id.main_parent_view);
daddyLayout.setFitsSystemWindows(false);
daddyLayout.invalidate();
这个好像没有效果,像这样:
如果我在 main_parent_view
中将 fitSystemWindows
设置为 false,状态栏填充将消失并且有效,但显然 影响每个片段 。
看到了同样的问题。通过从 activity 声明中删除 fitSystemWindows 并将 paddingTop 添加到片段中,在我的应用程序中解决了这个问题。显然不是一个理想的解决方案,但似乎有效。
您可以使用 CoordinatorLayout
作为您的 activity 根视图,然后 setFitsSystemWindows(boolean)
将起作用。
这是因为,如本 blog post 中所述,DrawerLayout
和 CoordinatorLayout
对于 fitsSystemWindows
如何应用于它们都有不同的规则 - 它们都使用它来插入他们的 child 视图,但也在每个 child 上调用 dispatchApplyWindowInsets()
,允许他们访问 fitsSystemWindows="true"
属性.
这与 FrameLayout
等布局的默认行为不同,其中当您使用 fitsSystemWindows="true"
时会消耗所有插图,盲目应用填充而不通知任何 child 视图(即博客的 'depth first' 部分 post).
我已经在 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);
}
好吧,你在那里处于两难境地,因为一方面你需要应用插图(因为 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
)。
如果您有 "materialish" 布局(CoordinatorLayout
、DrawerLayout
)之一作为根布局,那么子级将被分派那些 window 插图。
另一种选择是继承 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;
}
您可以查看
简单地说
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);