Android - fitsSystemWindows 问题 属性

Android - Problem with fitsSystemWindows property

我需要你的帮助来理解一个奇怪的行为。当我将 fitsSystemWindows 属性 设置为 'true' 时,导航栏隐藏了我布局的某些部分,请参见下图:

当我设置为 false 时,我有这种行为(没关系):

当我阅读 Android 文档和 Whosebug 上的许多帖子时,我理解它应该与此行为完全相反:https://developer.android.com/reference/android/view/View#attr_android:fitsSystemWindows。 第一种情况 fitsSystemWindows='true' 应该没问题,第二种情况应该被导航栏隐藏,我错了吗?

有人可以向我解释发生了什么事吗?我的 targetVersionSdk 是 29,我在许多版本(Android 6,7 10 和 11)上测试过它。也许它特定于 CoordinatorLayout ?感谢您的解释:)

这是我的 xml 布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="[true or false]">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            android:minHeight="?attr/actionBarSize"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    </com.google.android.material.appbar.AppBarLayout>

    [...]

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_marginBottom="@dimen/activity_vertical_margin"
        android:layout_marginEnd="@dimen/activity_vertical_margin"
        android:src="@drawable/ic_arrow_forward_white_24dp" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

我认为该视图按预期工作。首先,您需要了解插图及其传递方式。 fitsSystemWindow 的默认行为是消耗所有插图并将它们应用为填充。但是 CoordinatorLayout、DrawerLayout 等 ViewGroup 会覆盖此行为。

这是 CoordinatorLayout 中覆盖该行为的代码片段。

    private void setupForInsets() {
        if (Build.VERSION.SDK_INT < 21) {
            return;
        }

        if (ViewCompat.getFitsSystemWindows(this)) {
            if (mApplyWindowInsetsListener == null) {
                mApplyWindowInsetsListener =
                        new androidx.core.view.OnApplyWindowInsetsListener() {
                            @Override
                            public WindowInsetsCompat onApplyWindowInsets(View v,
                                    WindowInsetsCompat insets) {
                                return setWindowInsets(insets);
                            }
                        };
            }

            ViewCompat.setOnApplyWindowInsetsListener(this, mApplyWindowInsetsListener);

            setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
        } else {
            ViewCompat.setOnApplyWindowInsetsListener(this, null);
        }
    }

如您所见,在 CoordinatorLayout 中应用 fitsSystemWindow 会导致其呈现系统 UI 下的内容。您需要做的是添加系统提供的 insets 并将其作为 margin 或 padding 应用到顶部和底部视图。

您可以使用 setOnApplyWindowInsetsListener() 来侦听插入并应用它。假设您有 bottomNav 作为底部视图,那么您可以执行类似的操作来说明底部插图。

ViewCompat.setOnApplyWindowInsetsListener(bottomNav) { view, insets ->
    bottomNav.updatePadding(bottom = insets.systemWindowInsetBottom)
    insets
}

您可以在 this 博客 post 中了解有关插图的更多信息。