沉浸状态栏

本文介绍了一种在Android应用中实现沉浸式状态栏的方法。包括通过代码调整状态栏的透明度、颜色,以及如何根据不同Android版本进行适配。此外,还提供了一段详细的Java代码示例,展示了如何创建沉浸式效果,并提供了对MIUI和Flyme系统的特别支持。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/guolin_blog/article/details/51763825

/**
     * [沉浸状态栏]
     */
    protected void steepStatusBar() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 透明状态栏
            getWindow().addFlags(
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            // 透明导航栏
            getWindow().addFlags(
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }
    }

1 适配状态栏
values-v19/style.xml—对应api19+手机型号在此调用。
values-v21/style.xml—对应api21+手机型号在此调用。
Android studio新建values-v19,values-v21
切换到project下

这里写图片描述
命名为values-v19,values-v21,封闭在里面粘贴复制styles.xml
http://blog.youkuaiyun.com/fan7983377/article/details/51604657
另外一种方法
1.在res-》values中ids.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="immersiveutil_fake_status_bar_view" type="id" />
</resources>

2.ImmersiveModeUtil.java

public class ImmersiveModeUtil {
    private static final int DEFAULT_STATUS_BAR_ALPHA = 112;
    private static final int FAKE_STATUS_BAR_VIEW_ID = R.id.immersiveutil_fake_status_bar_view;

    private static int mPreviousSystemUiVisibility;
    /**
     * 0: not support, 1:darkMode, 2: lightMode
     */
    private static int currentStatusBarStyle;

    // 判断MIUI系统
    private static boolean sIsMiuiV6;

    static {
        try {
            Class<?> sysClass = Class.forName("android.os.SystemProperties");
            Method getStringMethod = sysClass.getDeclaredMethod("get", String.class);
            sIsMiuiV6 = "V6".equals((String) getStringMethod.invoke(sysClass, "ro.miui.ui.version.name"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 全屏Frag
     */
    public static final int FULL_SCREEN_VISIBILITY =
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                    | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;


    /**
     * 布局全屏会占用statusbar区域,通常配合设置状态栏背景为透明色。
     */
    public static final int LAYOUT_STABLE_AND_FULLSCREEN_VISIBILITY =
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;

    /**
     * 请求全屏,隐藏状态和和导航栏。使用场景:视频播放
     *
     * @param activity
     */
    public static void requestFullScreen(@NonNull Activity activity) {
        setSystemUiVisibility(activity, FULL_SCREEN_VISIBILITY);
    }

    /**
     * 退出全屏,进入全屏前,缓存systemui状态
     *
     * @param activity
     */
    public static void quitFullScreen(@NonNull Activity activity) {
        View decorView = activity.getWindow().getDecorView();
        int systemUiVisibility = decorView.getSystemUiVisibility();
        systemUiVisibility &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
        systemUiVisibility &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
        systemUiVisibility &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
        systemUiVisibility &= ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
        systemUiVisibility &= ~View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        systemUiVisibility &= ~View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        decorView.setSystemUiVisibility(systemUiVisibility);
    }

    /**
     * @param activity
     * @param systemUiVisibility
     */
    public static void setSystemUiVisibility(@NonNull Activity activity, int systemUiVisibility) {
        View decorView = activity.getWindow().getDecorView();
        mPreviousSystemUiVisibility = decorView.getSystemUiVisibility();
        decorView.setSystemUiVisibility(systemUiVisibility);
    }

    /**
     * 恢复
     *
     * @param activity
     */
    public static void restorePreviousSystemUiVisibility(@NonNull Activity activity) {
        if (mPreviousSystemUiVisibility != 0) {
            activity.getWindow().getDecorView().setSystemUiVisibility(mPreviousSystemUiVisibility);
        } else {
            setDefaultImmersiveMode(activity);
        }
    }

    /**
     * App默认的沉浸式默认
     *
     * @param activity
     */
    public static void setDefaultImmersiveMode(@NonNull Activity activity) {
        final boolean darkMode = setStatusBarDarkMode(activity, true);
        if (darkMode) {
            setStatusBarBgColor(activity, Color.WHITE);
        }
    }

    /**
     * 设置状态栏背景透明且layoutFullscreen
     *
     * @param activity
     */
    public static void setStatusBarTransparent(@NonNull Activity activity) {
        final Window window = activity.getWindow();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.setStatusBarColor(Color.TRANSPARENT);
            final int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
            window.getDecorView().setSystemUiVisibility(systemUiVisibility | LAYOUT_STABLE_AND_FULLSCREEN_VISIBILITY);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.getWindow()
                    .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

    /**
     * 设置状态栏颜色
     *
     * @param activity 需要设置的 activity
     * @param color    状态栏颜色值
     */
    public static void setStatusBarBgColor(@NonNull Activity activity, @ColorInt int color) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            activity.getWindow().setStatusBarColor(color);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
            View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
            if (fakeStatusBarView != null) {
                if (fakeStatusBarView.getVisibility() == View.GONE) {
                    fakeStatusBarView.setVisibility(View.VISIBLE);
                }
                fakeStatusBarView.setBackgroundColor(color);
            } else {
                decorView.addView(createStatusBarView(activity, color));
            }
            setRootView(activity);
        }
    }

    /**
     * 先判断主流系统,然后MIUI系统,最后Flyme
     *
     * @param activity
     * @param isFontColorDark 深色字体(Light)模式
     * @return 是否设置成功
     */
    @TargetApi(Build.VERSION_CODES.M)
    public static boolean setStatusBarDarkMode(@NonNull Activity activity, boolean isFontColorDark) {
        boolean result = setCommonStatusBarDarkMode(activity, isFontColorDark);
        if (!result) {
            result = setMIUIStatusBarDarkIcon(activity, isFontColorDark);

            if (!result) {
                result = setMeizuStatusBarDarkIcon(activity, isFontColorDark);
            }
        }
        if (result) {
            currentStatusBarStyle = isFontColorDark ? 2 : 1;
        }
        return result;
    }

    /**
     * 生成一个和状态栏大小相同的半透明矩形条
     *
     * @param activity 需要设置的activity
     * @param color    状态栏颜色值
     * @return 状态栏矩形条
     */
    private static View createStatusBarView(Activity activity, @ColorInt int color) {
        // 绘制一个和状态栏一样高的矩形
        View statusBarView = new View(activity);
        LinearLayout.LayoutParams params =
                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight());
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(color);
        statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID);
        return statusBarView;
    }

    /**
     * 设置根布局参数
     */
    private static void setRootView(Activity activity) {
        ViewGroup parent = activity.findViewById(android.R.id.content);
        for (int i = 0, count = parent.getChildCount(); i < count; i++) {
            View childView = parent.getChildAt(i);
            if (childView instanceof ViewGroup) {
                childView.setFitsSystemWindows(true);
                ((ViewGroup) childView).setClipToPadding(true);
            }
        }
    }

    /**
     * 计算状态栏颜色
     *
     * @param color color值
     * @param alpha alpha值
     * @return 最终的状态栏颜色
     */
    private static int calculateStatusColor(@ColorInt int color, int alpha) {
        if (alpha == 0) {
            return color;
        }
        float a = 1 - alpha / 255f;
        int red = color >> 16 & 0xff;
        int green = color >> 8 & 0xff;
        int blue = color & 0xff;
        red = (int) (red * a + 0.5);
        green = (int) (green * a + 0.5);
        blue = (int) (blue * a + 0.5);
        return 0xff << 24 | red << 16 | green << 8 | blue;
    }

    /**
     * 已在style中配置
     * 官方及主流rom
     *
     * @param activity
     */
    public static boolean setCommonStatusBarDarkMode(@NonNull Activity activity, boolean isFontColorDark) {
        boolean result = false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            View decor = activity.getWindow().getDecorView();
            int ui = decor.getSystemUiVisibility();
            if (isFontColorDark) {
                ui |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            } else {
                ui &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            }
            decor.setSystemUiVisibility(ui);
            // api>=23 默认成功
            result = true;
        }
        return result;
    }

    /**
     * set status bar darkmode
     *
     * @param isFontColorDark
     * @param activity
     */
    public static boolean setMIUIStatusBarDarkIcon(@NonNull Activity activity, boolean isFontColorDark) {
        boolean result = false;
        if (sIsMiuiV6) {
            Class<? extends Window> clazz = activity.getWindow().getClass();
            try {
                int darkModeFlag = 0;
                Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                extraFlagField.invoke(activity.getWindow(), isFontColorDark ? darkModeFlag : 0, darkModeFlag);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 修改魅族状态栏字体颜色 Flyme 4.0
     */
    private static boolean setMeizuStatusBarDarkIcon(@NonNull Activity activity, boolean isFontColorDark) {
        boolean result = false;
        try {
            WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
            Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
            Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
            darkFlag.setAccessible(true);
            meizuFlags.setAccessible(true);
            int bit = darkFlag.getInt(null);
            int value = meizuFlags.getInt(lp);
            if (isFontColorDark) {
                value |= bit;
            } else {
                value &= ~bit;
            }
            meizuFlags.setInt(lp, value);
            activity.getWindow().setAttributes(lp);
            result = true;
        } catch (Exception e) {
            //e.printStackTrace();
        }
        return result;
    }

    /**
     * @return 1:不支持,0:支持
     */
    public static int canSetStatusBarStyle() {
        int status = 1;
        // 成功设置过,或者API>=23
        if (currentStatusBarStyle != 0 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            status = 0;
        }
        return status;
    }

    /**
     * Return the status bar's height.
     *
     * @return the status bar's height
     */
    public static int getStatusBarHeight() {
        Resources resources = Resources.getSystem();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        return resources.getDimensionPixelSize(resourceId);
    }

}

参考文章

### 安卓沉浸状态栏的实现方法 #### 方法一:通过 `Theme` 和 `styles.xml` 设置透明状态栏 可以通过自定义主题的方式,在 `res/values/styles.xml` 文件中修改应用的主题样式,从而实现沉浸状态栏的效果。 ```xml <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- 状态栏颜色设置为透明 --> <item name="android:windowTranslucentStatus">true</item> <!-- 如果需要全屏模式可以加上以下属性 --> <item name="android:windowFullscreen">true</item> </style> ``` 此方法适用于 Android 4.4 (API Level 19) 及以上版本[^2]。需要注意的是,如果设置了 `android:windowTranslucentStatus=true`,则需要手动调整布局以防止内容被状态栏遮挡。 --- #### 方法二:通过代码动态设置沉浸状态栏 可以在 Activity 的 `onCreate()` 方法中通过 Java 或 Kotlin 动态设置状态栏的颜色和透明度。 ##### 示例代码(Java) ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } // 对于 Android 5.0 (Lollipop) 及以上的设备,可以直接设置状态栏颜色 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getWindow(); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(Color.TRANSPARENT); // 设置透明色 } ``` 对于更高版本的 Android 系统,还可以使用 `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN` 来进一步优化沉浸体验: ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { View decorView = getWindow().getDecorView(); int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; decorView.setSystemUiVisibility(uiOptions); } ``` 这种方法能够兼容更多场景,并提供更灵活的状态栏定制能力[^3]。 --- #### 方法三:结合 XML 布局文件适配沉浸状态栏 为了确保页面内容不会被状态栏覆盖,可以在布局文件中使用 `android:fitsSystemWindows="true"` 属性。该属性会让视图自动留出足够的空间给系统窗口(如状态栏),从而避免内容错位。 ```xml <TextView android:fitsSystemWindows="true" android:clipToPadding="true" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/mask_tags_3" android:text="你好,沉浸状态栏"/> ``` 此外,也可以通过动态计算状态栏的高度并将其作为 padding 应用于顶部控件来解决这个问题: ```java int statusBarHeight = getStatusBarHeight(this); ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) findViewById(R.id.ll_bar).getLayoutParams(); params.topMargin += statusBarHeight; private int getStatusBarHeight(Context context) { int result = 0; int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = context.getResources().getDimensionPixelSize(resourceId); } return result; } ``` --- ### 注意事项 - **兼容性**:不同版本的 Android 系统对沉浸状态栏的支持程度有所不同,因此建议针对 API 版本进行条件判断。 - **深色模式支持**:从 Android 10 开始引入了深色模式,开发者需注意状态栏文字颜色是否会与背景冲突。可通过 `WindowInsetsController` 调整状态栏的文字亮度[^1]。 - **第三方库**:如果项目复杂度较高,可考虑使用成熟的开源框架(如 ImmersionBar)简化开发流程。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值