在状态栏和导航栏下绘制内容,同时保持fitsSystemWindows =“ true”行为

时间:2018-11-19 08:40:03

标签: android android-layout

我正在尝试在状态栏和导航栏下绘制内容,使它们完全透明,同时还利用fitsSystemWindows="true"

对于状态栏,fitsSystemWindows="true"和以下代码可以正常工作。

getWindow() .getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
getWindow().setStatusBarColor(Color.TRANSPARENT);

enter image description here

但是,当我添加以下行以在导航栏下绘制内容时,我们从fitsSystemWindows="true"获得的插图不再可用。

getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

enter image description here

某些解决方案包括像这样获取状态栏和导航栏高度

getResources().getDimensionPixelSize(getResources().getIdentifier("status_bar_height", "dimen", "android"));

并将其用作填充。

但是,不建议使用此方法。

在状态栏和导航栏下绘制内容时,是否有任何方法可以保持fitsSystemWindows =“ true”的行为?预先感谢。

1 个答案:

答案 0 :(得分:1)

使用标志

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window w = getWindow();
            w.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
            w.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
           w.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

        }

然后使用这两种方法推送视图

@SuppressLint("NewApi")
public static boolean hasImmersive(Context ctx) {

    if (!cached) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            hasImmersive = false;
            cached = true;
            return false;
        }
        Display d = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

        DisplayMetrics realDisplayMetrics = new DisplayMetrics();
        d.getRealMetrics(realDisplayMetrics);

        int realHeight = realDisplayMetrics.heightPixels;
        int realWidth = realDisplayMetrics.widthPixels;

        DisplayMetrics displayMetrics = new DisplayMetrics();
        d.getMetrics(displayMetrics);

        int displayHeight = displayMetrics.heightPixels;
        int displayWidth = displayMetrics.widthPixels;

        hasImmersive = (realWidth > displayWidth) || (realHeight > displayHeight);
        cached = true;
    }

    return hasImmersive;
}

相应地应用填充

 if (hasImmersive(this)) {
            yourView.setPadding(0, 0, 0, getSoftButtonsBarHeight());

        }

并获取系统软键的高度

 @SuppressLint("NewApi")
    private int getSoftButtonsBarHeight() {
        // getRealMetrics is only available with API 17 and +
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            DisplayMetrics metrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(metrics);
            int usableHeight = metrics.heightPixels;
            getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
            int realHeight = metrics.heightPixels;
            if (realHeight > usableHeight)
                return realHeight - usableHeight;
            else
                return 0;
        }
        return 0;
    }

屏幕截图 Here is the screen shot

编辑:要保留通知栏的fitsSystemWindows="true"行为,请在将窗口插图应用于FLAG_LAYOUT_NO_LIMITS后添加View和其他标志其中fitsSystemWindows设置为true。这样可以确保在应用无限制标志之前已经正常应用了插图。

yourViewWithFitsSystemWindows.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
        @Override
        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
            if(insets.getSystemWindowInsetTop() == 0) return insets; // This is needed.
            v.onApplyWindowInsets(insets);

            getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
            // add other flags
            return insets;
        }
    });

这与设置底部填充一起提供了所需的结果。