刘海屏适配

先参考一下各厂商的刘海屏适配api


华为:https://devcenter-test.huawei.com/consumer/cn/devservice/doc/50114 
小米:https://dev.mi.com/console/doc/detail?pId=1293
Oppo:https://open.oppomobile.com/service/message/detail?id=61876
Vivo:https://dev.vivo.com.cn/documentCenter/doc/103

 

适配步骤

1.判断手机厂商,

虽然谷歌9.0已经给出了刘海屏适配的方法,但是不同厂商在刘海屏适配方面有自己的api,所以再刘海屏适配之前要先确定厂商,然后根据厂商给的api获取刘海屏高度,做屏幕适配才最方便,有效.

 

/**
     * 是否是魅族手机(系统)
     * @return
     */
    public static boolean isFlyme() {
        return "Meizu".equalsIgnoreCase(Build.BRAND);
    }

    /**
     * 是否是华为荣耀
     * @return
     */
    public static boolean isHuawei(){
        return "huawei".equalsIgnoreCase(Build.BRAND)||"Honor".equalsIgnoreCase(Build.BRAND);
    }

    /**
     * 是否是三星
     * @return
     */
    public static boolean isSamsung(){
        return "samsung".equalsIgnoreCase(Build.BRAND);
    }

    /**
     * 是否是小米
     * @return
     */
    public static boolean isXiaomi(){
        return "xiaomi".equalsIgnoreCase(Build.BRAND);
    }

    /**
     * 是否是oppo
     * @return
     */
    public static boolean isOppo(){
        return "oppo".equalsIgnoreCase(Build.BRAND);
    }

2.判断手机是否有刘海屏

官方的方式是

    /**
     * 判断是否有刘海
     * @param window
     * @return
     */ 
private boolean hasDisplayCutout(Window window) {

        DisplayCutout displayCutout;
        View rootView = window.getDecorView();
        WindowInsets insets = rootView.getRootWindowInsets();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && insets != null){
            displayCutout = insets.getDisplayCutout();
            if (displayCutout != null){
                if (displayCutout.getBoundingRects() != null && displayCutout.getBoundingRects().size() > 0 && displayCutout.getSafeInsetTop() > 0){
                    return true;
                }
            }
        }
        return false; 
    }

这边还要考虑各个厂商 所以分别做判断

 /**
     * 是否是刘海屏,仅支持小米华为oppo
     *
     * @param activity
     * @return
     */
    public static boolean isNotchPhone(Activity activity) {
        if (PhoneBrandUtil.isXiaomi()) {
            return "1".equals(getProperty("ro.miui.notch", "0"));
        } else if (PhoneBrandUtil.isHuawei()) {
            return hasNotchInScreen(activity);
        } else if (PhoneBrandUtil.isOppo()) {
            return hasNotInOppoScreen(activity);
        } else {
            return false;
        }
    }
/**
     * 华为手机是否有刘海屏
     *
     * @param context
     * @return
     */
    private static boolean hasNotchInScreen(Context context) {
        boolean ret = false;
        try {
            ClassLoader cl = context.getClassLoader();
            Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
            ret = (boolean) get.invoke(HwNotchSizeUtil);
        } catch (ClassNotFoundException e) {
            Log.e("test", "hasNotchInScreen ClassNotFoundException");
        } catch (NoSuchMethodException e) {
            Log.e("test", "hasNotchInScreen NoSuchMethodException");
        } catch (Exception e) {
            Log.e("test", "hasNotchInScreen Exception");
        } finally {
            return ret;
        }
    }
 /**
     * oppo手机是否是刘海屏
     *
     * @param context
     * @return
     */
    private static boolean hasNotInOppoScreen(Context context) {
        try {
            return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取系统属性
     *
     * @param key
     * @param defaultValue
     * @return
     */
    private static String getProperty(String key, String defaultValue) {
        String value = defaultValue;
        try {
            Class<?> c = Class.forName("android.os.SystemProperties");
            Method get = c.getMethod("get", String.class, String.class);
            value = (String) (get.invoke(c, key, "0"));
        } catch (Exception e) {
            return value;
        }
        return value;
    }

 

3.设置是否让内容延伸进刘海

可以通过WindowManager.LayoutParam设置刘海屏的3个参数,设置第二个为 是activity的控件可以延伸进刘海区,

//全屏模式,内容下移,非全屏模式,内容不受影响   
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT = 0;
//允许内容延伸进刘海区
public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER = 2;
//不允许内容延伸进刘海区
 public static final int LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES = 1;


4.获取刘海屏高度

通过各厂商的获取刘海的高度都有自己的api和默认高度,一般刘海的高度会小于等于状态栏的高度,所以,可以先取状态栏高度作为默认值,如果取不到刘海高度,就以状态栏高度为准.

  /**
     * 获取状态栏高度,如果是刘海屏则获取刘海高度,目前仅适配华为、oppo和小米刘海屏
     *
     * @param activity
     * @return
     */
    public static int getNotchHigh(Activity activity) {
        int statusHigh =heightForDisplayCutout(activity);
        //如果是小米手机
        if (PhoneBrandUtil.isXiaomi()) {
            //是刘海屏
            if ("1".equals(getProperty("ro.miui.notch", "0"))) {
                //https://dev.mi.com/console/doc/detail?pId=1293,取刘海高度89
                return 89;
            } else {
                return statusHigh;
            }
        } else if (PhoneBrandUtil.isHuawei()) {
            if (hasNotchInScreen(activity)) {
                return getNotchSize(activity)[1];
            } else {
                return statusHigh;
            }
        } else if (PhoneBrandUtil.isOppo()) {
            if (hasNotInOppoScreen(activity)) {
                //https://open.oppomobile.com/wiki/doc#id=10159
                return 80;
            } else {
                return statusHigh;
            }
        } else {
            return statusHigh;
        }
    }

 /**
     * 获取状态栏高度
     *
     * 
     * @return
     */
  public int heightForDisplayCutout(){
        int resID = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resID > 0){
            return getResources().getDimensionPixelSize(resID);
        }
        return 96;
    }

 

6.控件适配 

一般就是 让控件的父容器做paddingTop=刘海的高度,或者控件marginTop=刘海高度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值