Android 主流 app 的沉浸式效果

什么是沉浸式呢?就是状态栏透明,将 activity 布局延伸到整个屏幕,所呈现的一种模式效果。

白底黑字式

状态栏透明,深色图标文字是地图 app 常见效果:
Android 主流 app 的沉浸式效果_第1张图片
关于状态栏的展示效果,官方也是调整多多。在 android4.4 版本之前,用户除了通过全屏模式使之消失外,并不能对状态栏操作什么。而在 android5.0 之前,官方提供了 FLAG_TRANSLUCENT_STATUS 标志位,来控制状态栏是否实现渐变的半透明效果。而到了 android5.0 之后,FLAG_TRANSLUCENT_STATUS 标志位所控制的样式也做了调整,从渐变变成了纯粹的半透明。而到了 android6.0 之后,FLAG_TRANSLUCENT_STATUS 效果再次改变,设置此标志可使状态栏全透明。

Android5.0 以上状态栏透明的代码示例:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
     
        // android 5.0+ 状态栏透明
        Window window = getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        window.getDecorView().setSystemUiVisibility(option);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(Color.TRANSPARENT);
    }

考虑到状态栏被设置为透明后,状态栏上的文字和图标存在看不清的情况。Android6.0 以上,系统提供了API 来修改状态栏的字体背景色:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
     
        int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
        getWindow().getDecorView().setSystemUiVisibility(option);
    }

关于沉浸式,难点在于特殊机型的适配工作上。例如小米和魅族手机,在 android4.4 版本之后,FLAG_TRANSLUCENT_STATUS 标志位便显示为全透明效果,而且自 android4.4 之后,其便提供了设置状态栏图标和文字颜色的内部方法。

特殊(1)魅族

详情参考开放平台,下载 StatusbarColorUtils 类,接口见下:

    /**
     * 设置状态栏字体图标颜色
     *
     * @param activity 当前activity
     * @param dark     是否深色 true为深色 false 为白色
     */
    public static void setStatusBarDarkIcon(Activity activity, boolean dark) {
     
        setStatusBarDarkIcon(activity, dark, true);
    }
特殊(2)OPPO

详情参考开放平台,对 Android 版本是 6.0 及以后的 OPPO 机型,使用 Google 提供View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 的 Flag 来设置状态栏图标黑色显示效果。

对 Android5.1 版本并且是 ColorOS3.0 的 OPPO 机型使用 ColorOS 提供 SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT 的 Flag 来设置状态栏图标黑色效果,由于该标记未公开,开发者需要在应用代码中定义。

    final int SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT = 0x00000010;
    Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.getDecorView().setSystemUiVisibility(SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT);

为方便开发者对于 OPPO 机型的反色适配,提供了用于设置状态栏显示效果的接口方法,开发者可以根据应用需要动态设置状态栏图标为白色或是黑色。接口传入值 ture 时状态栏图标为黑色,接口转入值为 false 状态栏图标为白色:

    public void setLightStatusBarIcon(boolean lightMode) {
     
        Window window  = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        int vis = window.getDecorView().getSystemUiVisibility();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
     
            if (lightMode) {
     
                vis |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            } else {
     
                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.L) {
     
            if (lightMode) {
     
                vis |= SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT;
            } else {
     
                vis &= ~SYSTEM_UI_FLAG_OP_STATUS_BAR_TINT;
            }
        }
        window.getDecorView().setSystemUiVisibility(vis);
    }
特殊(3)小米

详情参考开放平台,在 Android 6.0 以前,Android 没有方法可以实现“状态栏黑色字符”效果,因此 MIUI 自己做了一个接口。在 Android 6.0 及以上版本,Android 提供了标准的方法实现“状态栏黑色字符”效果,但这个方法和 MIUI 的方法产生了冲突。

在新的 MIUI 开发版 7.7.13 及以后版本(基于 Android 6.0 ),设置代码:

    Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

在旧的 MIUI 版本,仍然需要使用 MIUI 原有的方法,即:

    public void setStatusBarDarkMode(boolean darkmode, Activity activity) {
     
        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(), darkmode ? darkModeFlag : 0, darkModeFlag);
        } catch (Exception e) {
     
            e.printStackTrace();
        }
    }

待续

你可能感兴趣的:(android,随笔,沉浸适配)