Android 适配刘海屏(沉浸式改变状态栏颜色与透明状态栏含Android6.0以下适配)

上代码

/**
 * Created by Android Studio.
 * ProjectName: ----
 * Author: HongYu ()
 * Create date: by Baron on 2020/12/1 10:42 AM
 * Last modified by YanTao ()
 * Last modified date: by Baron on 2020/12/1 10:42 AM
 * \ --------------------------------------------
 * \| The only thing that is constant is change!  |
 * \ --------------------------------------------
 * \  \
 * \   \   \_\_    _/_/
 * \    \      \__/
 * \           (oo)\_______
 * \           (__)\       )\/\
 * \               ||----w |
 * \               ||     ||
 */
public class StatusBarUtils {
    private static final int FAKE_STATUS_BAR_VIEW_ID = R.id.fake_status_bar_view;

    public static int getHeight(Context context) {
        int statusBarHeight = 0;
        try {
            int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen",
                    "android");
            if (resourceId > 0) {
                statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusBarHeight;
    }

    ///   Android 5.0+   /开始

    //设置状态栏颜色的功能:
    public static void setColor(@NonNull Window window, @ColorInt int color) {
        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.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            window.setStatusBarColor(color);
            //设置沉浸式的颜色(避免北京颜色太亮出现看不清沉浸式的情况)但是官方仅在Android 6.0以上版本提供支持
            setTextDark(window, !isDarkColor(color));

        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //设置状态栏颜色
            //在设置纯颜色时,我们还需要将该颜色与黑色进行1:1的混合。为什么要这么设置呢?
            // 因为状态栏的文字和图标颜色默认是白色的,并且在Android 5.0以下是不能修改的,所以如果修改成较浅的颜色,
            // 就会导致状态栏文字看不清的现象,因此做一个比较暗的浮层效果更好一些。
            setColor(window, ColorUtils.blendARGB(Color.TRANSPARENT, color, 0.5f), false);
        }

    }
    //为了便于对Activity直接操作,可以再增加一个如下方法:
    public static void setColor(Context context, @ColorInt int color) {
        if (context instanceof Activity) {
            setColor(((Activity) context).getWindow(), color);
        }

    }
    private static void setTextDark(Window window, boolean isDark) {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            View decorView = window.getDecorView();
            int systemUiVisibility = decorView.getSystemUiVisibility();
            if (isDark) {
                decorView.setSystemUiVisibility(systemUiVisibility | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            } else {
                decorView.setSystemUiVisibility(systemUiVisibility & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            }

        }
    }
    public static void setTextDark(Context context, boolean isDark) {
        if (context instanceof Activity) {
            setTextDark(((Activity) context).getWindow(), isDark);
        }
    }
    //为了防止背景颜色太亮所以需要进行判断是否是深色与亮色(只适配6.0以上的手机)
    public static boolean isDarkColor(@ColorInt int color) {
        return ColorUtils.calculateLuminance(color) < 0.5;
    }
    //那么6.0一下的手机怎么办呢来了
    //目前Android 5.0-6.0的手机只有小米MIUI和魅族Flyme系统提供了支持。小米MIUI的设置方法如下:
    private static void setMIUIDark(Window window, boolean isDark) {//小米
        try {
            Class<? extends Window> clazz = window.getClass();
            int darkModeFlag;
            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(window, isDark ? darkModeFlag : 0, darkModeFlag);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void setFlymeDark(Window window, boolean isDark) {//魅族
        if (window != null) {
            try {
                WindowManager.LayoutParams lp = window.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 (isDark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public static boolean isMIUI() {
        String manufacturer = Build.MANUFACTURER;
        //这个字符串可以自己定义,例如判断华为就填写huawei,魅族就填写meizu
        if ("xiaomi".equalsIgnoreCase(manufacturer)) {
            return true;
        }
        return false;
    }

    //设置状态栏透明(可以设置图片)
    public static void setTransparent(@NonNull Window window) {
        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.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
            window.setStatusBarColor(Color.TRANSPARENT);

         }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//android 4.0修改状态栏透明
            setColor(window, 0x80000000, true);
        }
    }
    //同样针对Activity,增加如下方法:
    public static void setTransparent(Context context) {
        if (context instanceof Activity) {
            setTransparent(((Activity) context).getWindow());

        }
    }
    ///   Android 4.4+   /
   // 下面针对Android 4.4-5.0的手机进行实现。实现原理是将内容布局设为全屏,然后在布局的顶部添加一个
    // 和状态栏一样高度的View,将该View的背景设置成我们想要的颜色。当需要将状态栏设置纯颜色时
    // ,为了和Android 5.0以上版本保持一致,我们对内容布局的上边设置一个padding,大小为状态栏的高度。
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static void setColor(@NonNull Window window, @ColorInt int color,
                                boolean isTransparent) {
        Context context = window.getContext();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        ViewGroup decorView = (ViewGroup) window.getDecorView();
        View contentView = decorView.findViewById(android.R.id.content);
        if (contentView != null) {
            contentView.setPadding(0, isTransparent ? 0 : getHeight(context), 0, 0);
        }
        View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
        if (fakeStatusBarView != null) {
            fakeStatusBarView.setBackgroundColor(color);
            if (fakeStatusBarView.getVisibility() == View.GONE) {
                fakeStatusBarView.setVisibility(View.VISIBLE);
            }
        } else {
            // 绘制一个和状态栏一样高的矩形
            View statusBarView = new View(context);
            FrameLayout.LayoutParams layoutParams =
                    new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                            getHeight(context));
            statusBarView.setLayoutParams(layoutParams);
            statusBarView.setBackgroundColor(color);
            statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID);
            decorView.addView(statusBarView);
        }
    }
   ///   特殊场景   /现在来针对一些特殊场景进行适配,比如启动页、刘海屏和弹窗等等。
    //其实Android P已经出可以适配刘海屏幕的代码两将下面代码放到MainActivity的onreate里面

   /* // 适配刘海屏
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
        layoutParams.layoutInDisplayCutoutMode =
                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
        getWindow().setAttributes(layoutParams);
    }*/

    //但是一些手机厂商的刘海屏手机系统版本是低于Android P的,
    // 不过也都提供了适配的方法。适配方式是在AndroidManifest.xml文件里的application标签下添加如下代码:
/*  <!-- 允许绘制到小米刘海屏机型的刘海区域 -->
    <meta-data
    android:name="notch.config"
    android:value="portrait" />
<!-- 允许绘制到华为刘海屏机型的刘海区域 -->
    <meta-data
    android:name="android.notch_support"
    android:value="true" />
<!-- 允许绘制到oppo、vivo刘海屏机型的刘海区域 -->
    <meta-data
    android:name="android.max_aspect"
    android:value="2.2" />*/

//另外,对于Android 5.0以下的手机,适配完刘海屏后会在顶部多一块黑色半透明的View,那我们将其改成全透明的,修改onCreate()方法如下:
/*@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);
    StatusBarUtils.setTransparent(this);
    // 适配刘海屏
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
        layoutParams.layoutInDisplayCutoutMode =
                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
        getWindow().setAttributes(layoutParams);
    }
    // 适配Android 4.4
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        StatusBarUtils.setColor(getWindow(), Color.TRANSPARENT, true);
    }
}*/

}

使用方法

 StatusBarUtils.setColor(this, getResources().getColor(R.color.colorAccent));
 StatusBarUtils.setTransparent(this);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王鑫林呀!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值