0

我在 Android 11 中面临全屏沉浸式模式的问题。我的主要活动布局文件看起来像这样,

<DrawerLayout .... android:fitsSystemWindows="true">
    <CoordinatorLayout>
          <AppBarLayout>
              <FragmentContainerView>

我正在尝试从我的片段中显示全屏模式。在 Android 11 之前,我曾经从 Fragment 的 onCreate 视图调用以下函数

fun hideStatusBar (activity: AppCompatActivity?) {
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) }

我将其替换为,

fun hideStatusBar(activity: AppCompatActivity?) {
@Suppress("DEPRECATION")
if (isAtLeastAndroid11()) {
    val controller = activity?.window?.insetsController
    controller?.hide(WindowInsets.Type.statusBars())
} else {
    activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
}

这会按预期删除状态栏,但会在状态栏区域的屏幕顶部留下一个空白区域

带状态栏:

在此处输入图像描述

状态栏已移除:

在此处输入图像描述

我试图测量片段内的窗口插图并调整片段容器的高度

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    if(isAtLeastAndroid11()){
        WindowCompat.setDecorFitsSystemWindows(requireActivity().window, false)
        setUiWindowInsets()
    }
}

private fun setUiWindowInsets() {
    ViewCompat.setOnApplyWindowInsetsListener(rootView) { _, insets ->
    
        posTop = insets.getInsets(WindowInsetsCompat.Type.systemBars()).top
        posBottom = insets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom

        rootView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
            updateMargins(
                top = posTop,
                bottom = posBottom)
        }

        insets
    }
}

但是我的 ViewCompat.setOnApplyWindowInsetsListener 永远不会被调用。根据本文,Coordinator Layout 使用 onApplyWindowInsets 回调,并且子级不会收到任何回调。rootView是我的 Fragment 的根视图(一个相对布局),它被放置在我的布局层次结构中的 FragmentContainer 中。

Android 10 和 11 之间的比较

在此处输入图像描述

我的问题:

  1. 我应该如何setOnApplyWindowInsetsListener在片段中调用我的方法?
  2. 当状态栏隐藏时,我应该如何让我的协调器布局知道占据全屏?

参考:协调器布局消耗回调:

  1. setOnApplyWindowInsetsListener 从未调用过
  2. https://medium.com/androiddevelopers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec
  3. https://newbedev.com/fitssystemwindows-effect-gone-for-fragments-added-via-fragmenttransaction
4

2 回答 2

0

问题来自应用程序栏。即使它是全屏的,它也会尽量防止内容与状态栏发生冲突,即使它是隐藏的。这是一个新的实现,也是为了防止手机缺口覆盖内容。

如果要使用整个屏幕,则应删除应用栏。如果确实需要操作工具提示,请使用底栏。

于 2021-10-01T23:58:06.577 回答
0

您可能必须fitsSystemWindows关闭标志(windowWindow 实例在哪里):

window.setDecorFitsSystemWindows(false);

所以我喜欢这样:

private void hideSystemUI() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        windowInsetsController.hide(WindowInsets.Type.statusBars());
        window.setDecorFitsSystemWindows(false);
    }
}

当然,你还需要在显示状态栏的时候设置flag:

private void showSystemUI() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        windowInsetsController.show(WindowInsets.Type.statusBars());
        window.setDecorFitsSystemWindows(true);
    }
}

仅供参考,您可能需要触发hideSystemUIshowSystemUIActivity.onWindowFocusChanged.

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    if (hasFocus) {
        if (isImmersive) {
            hideSystemUI();
        } else {
            showSystemUI();
        }
    }
}

(以上是Java,请翻译成Kotlin)

于 2021-10-02T03:23:12.400 回答