如何从SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION中恢复? [英] How to recover from SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION?

查看:693
本文介绍了如何从SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION中恢复?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题实际上是在更复杂的情况下出现的,涉及方向变化和纵向和横向布局的变化,但是在最小版本中,问题是这样的:

This problem actually arose in a more complex situation involving orientation changes and varying layouts for portrait and landscape but in it's minimal version the problem is this:

在常规和全屏布局之间来回切换,即e。:

We would like to switch back and forth between a "normal" and "fullscreen" layout, i. e.:


  • 一种布局,其中的内容仅占据导航栏和状态栏内部的空间

  • 一种布局,其中内容占据整个屏幕,并在导航栏和状态栏下滑动

要从普通模式切换要全屏显示,我们将使用:

To switch from normal to fullscreen we are using:

public static final int EXPAND_FLAGS = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;

getWindow().getDecorView().setSystemUiVisibility(EXPAND_FLAGS);

然后切换回去,我们尝试过:

And to switch back we tried:

public static final int SHRINK_FLAGS = View.SYSTEM_UI_FLAG_VISIBLE;

getWindow().getDecorView().setSystemUiVisibility(SHRINK_FLAGS);

所以,从这个

我们首先将其扩展至此:

we first "expand" to this:

,但收缩后退不起作用:

but "shrinking" back does not work:

因此,看来,虽然仅允许Activity在系统内部绘制用户界面仍然认为它应该为系统用户界面留出空间。

So, it seems that while the Activity is only allowed to draw inside of the system UI it still "thinks" it should leave space for the system UI.

所以我的问题是: SHRINK_FLAGS 在上面的代码中还是应该完全不同地做些什么?

So my question is: What should SHRINK_FLAGS be in my code above or what should I do completely differently?

W e正在使用 AppCompatActivity Theme.AppCompat.Light.DarkActionBar 主题。

We are using an AppCompatActivity with a Theme.AppCompat.Light.DarkActionBar theme.

推荐答案

似乎布局的根目录为 android:fitsSystemWindows = true 。由于某些我不知道的原因, fitsSystemWindows 在更改系统UI标志时无法正常工作。幸运的是,有一个解决此问题的方法。

Seems the root of your layout has android:fitsSystemWindows="true". For some reason, which I'm not aware of, fitsSystemWindows doesn't work well when changing system UI flags. Fortunately, there's a workaround for this problem.

首先,无条件设置扩展系统UI标志:

First, set expand system UI flags unconditionally:

getWindow().getDecorView().setSystemUiVisibility(
        View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
);

然后删除 android:fitsSystemWindows = true

Then remove android:fitsSystemWindows="true" from all ancestor views of the layout.

之后,创建一个布局,该布局将处理系统插图更改并根据其属性值添加或删除填充。那是最复杂的部分。您必须根据平台版本来不同地处理系统插入。对于低于20(Kitkat Watch)的版本,您必须覆盖 View.fitSystemWindows() 方法:

After that create a layout that will handle system insets changes and add or remove padding based on the value of its property. That's the most complicated part. You have to handle system insets differently depending on platform version. For versions below 20 (Kitkat Watch) you have to override View.fitSystemWindows() method:

@Override
protected boolean fitSystemWindows(final Rect insets) {
    if (mFit) {
        setPadding(insets.left, insets.top, insets.right, insets.bottom);
        // Do not propagate the system insets further.
        return true;
    } else {
        setPadding(0, 0, 0, 0);
        // Do not consume the insets and allow other views handle them.
        return false;
    }
}

对于大于或等于20的平台版本,您需要覆盖 View.onApplyWindowInsets () 方法,并与以前的方法相同:

For platform version greater or equal than 20 you need to override View.onApplyWindowInsets() method and to the same processing as in the previous method:

@Override
public WindowInsets onApplyWindowInsets(final WindowInsets insets) {
    if (mFit) {
        setPadding(
                insets.getSystemWindowInsetLeft(),
                insets.getSystemWindowInsetTop(),
                insets.getSystemWindowInsetRight(),
                insets.getSystemWindowInsetBottom()
        );
        return insets.consumeSystemWindowInsets();
    } else {
        setPadding(0, 0, 0, 0);
        return insets;
    }
}

最后为<$ c $创建一个setter c> mFit 字段,它将通知系统它必须再次应用插入:

And finally create a setter for the mFit field, which will notify the system that it must apply insets again:

mFit = fit;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
    requestApplyInsets();
} else {
    requestFitSystemWindows();
}

现在您可以调用 setFit(false)使视图布局位于系统UI后面,而 setFit(true)使布局适合系统窗口。

Now you can call setFit(false) to make your views layout behind the system UI and setFit(true) to make the layout fit system windows.

您可以在此处获得该布局的源代码。

You can get the source code for this layout here.

这篇关于如何从SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION中恢复?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆