android沉浸式状态栏

1,000 阅读2分钟

android4.4开始支持设置透明状态栏

在代码中设置

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}

通过查看WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS的官方注释,有这么一句话

When this flag is enabled for a window, it automatically sets the system UI visibility flags {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.

也可以这么设置

View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

当然也可以在values-v19/styles.xml,values-v21/styles.xml和values-v23/styles.xml中设置

//使布局侵入到状态栏,并且使状态栏透明。不会出现状态栏显示隐藏的过渡动画效果。
<item name="android:windowTranslucentStatus">true</item>

fitsSystemWindows

这个属性会使布局下移一个状态栏高度的距离,避免布局侵入到状态栏

如何使状态栏颜色和头布局保持一致

1. 如果布局头部是一个ImageView

这种情况下,ImageView侵入到状态栏,如果没有大的影响,其实可以不做处理.否则,建议做出的图片,其内容能尽量下移一下,避免被状态栏遮挡过多.android5.0以后可以通过Palette获取bitmap的颜色,来给预留的view设置颜色.

1.1 添加依赖
implementation 'com.android.support:palette-v7:27.1.1'
1.2 获取图片颜色并设置给预留view
//预留view
        final View insetView = null;
        //头部imageView
        final Bitmap bitmap = null;
        Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
            @Override
            public void onGenerated(@NonNull Palette palette) {
                Palette.Swatch mutedSwatch = palette.getMutedSwatch();
                if (null!=mutedSwatch){
                    insetView.setBackgroundColor(mutedSwatch.getRgb());
                }else {
                    Palette.Swatch vibrantSwatch = palette.getVibrantSwatch();
                    if (vibrantSwatch!=null){
                        insetView.setBackgroundColor(vibrantSwatch.getRgb());
                    }
                }
            }
        });

2.如果布局头部是个标题栏

2.1 在布局头部放置一个0dp高度的View
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_orientation="vertical">
<View android:layout_width="match_parent"
    android:layout_height="0dp"
    android:id="@+id/insetView"
>
</View>
<FrameLayout 
    android:layout_width="match_parent"
    android:id="@+id/content"
    android:layout_height="0dp"
    android:layout_weight="1">
</FrameLayout>
</LinearLayout>
2.2 在代码里获取状态栏高度
/**
     * 获取状态栏高度
     * @param context
     * @return
     */
    protected   int getStatusBarHeight(Context context) {
        int result = 0;
        int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resId > 0) {
            result = context.getResources().getDimensionPixelOffset(resId);
        }
        return result;
    }
2.3 设置预留view的高度和颜色
protected void setStatusHeightAndBackgroundColor(int height ,int color){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) insetView.getLayoutParams();
            layoutParams.height = height;
            insetView.setLayoutParams(layoutParams);
            insetView.setBackgroundColor(ContextCompat.getColor(this,color));
        }
    }

以上这样处理,在小米8刘海屏幕上也能完美适配 各大厂手机适配地址
oppo
vivo
识别小米手机
MIUI6沉浸式状态栏
MIUI 9 & 10“状态栏黑色字符”实现方法变更通知