Android 刘海、挖孔、水滴屏幕的状态高度获取与适配

  • Post author:
  • Post category:其他


一般需要处理状态栏的问题都是适配问题,适配就稍微有点麻烦,比如:刘海屏,水滴屏、以及刚刚不久出的挖孔屏等这类都属于刘海屏范围内,适配的话就要在各大厂商做处理了,比如华为:刚刚开始以为只需判断是否是刘海屏就好了,设置一个状态栏高度就好Ok了,结果不然:

状态栏高度:

  private fun setStatusHeight() {
        val layoutParams = base_head.layoutParams as LinearLayout.LayoutParams
        layoutParams.setMargins(0,StatusBarUtils.getStatusBarHeight(mContext),0,0)
        base_head.layoutParams = layoutParams
    }
/**
     * 获得通知栏高度
     */
    public static int getStatusBarHeight(Context context) {
        Class<?> c = null;
        Object obj = null;
        Field field = null;
        int x = 0, statusBarHeight = 0;
        try {
            c = Class.forName("com.android.internal.R$dimen");
            obj = c.newInstance();
            field = c.getField("status_bar_height");
            x = Integer.parseInt(field.get(obj).toString());
            statusBarHeight = context.getResources().getDimensionPixelSize(x);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return statusBarHeight;
    }


因为这里设置的是铺满全屏,需要重新计算状态栏高度,在小米、oppo、华为的刘海屏和水滴屏幕没有问题,但在华为的挖孔屏上出现问题,就是常见的重叠,其他品牌的手机因为没有,不知道有没有出现类似的问题,先说问题原因是:华为的状态栏高度是获取到了的值很小,只有26仔细看到话在挖孔的上面很小的空白处是有高度的那个就是状态栏高度,导致出现重叠的原因,解决方法就是获取挖孔的高度,把值设置进去就好了;

 /**
     * 获取华为刘海的高
     *
     * @param context
     * @return
     */
    public static int getNotchSizeAtHuawei(Context context) {
        int[] ret = new int[]{0, 0};
        try {
            ClassLoader cl = context.getClassLoader();
            Class<?> HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = HwNotchSizeUtil.getMethod("getNotchSize");
            ret = (int[]) get.invoke(HwNotchSizeUtil);

        } catch (ClassNotFoundException e) {
            Log.e("NotchScreenUtil", "getNotchSize ClassNotFoundException");
        } catch (NoSuchMethodException e) {
            Log.e("NotchScreenUtil", "getNotchSize NoSuchMethodException");
        } catch (Exception e) {
            Log.e("NotchScreenUtil", "getNotchSize Exception");
        }
        return ret[1];
    }


这个是专门针对华为过去的高度,其他品牌获取的值为0,现在只适配了这些后期有问题会补上。

/**
     * 是否有刘海屏
     *
     * @return
     */
    public static boolean hasNotchInScreen(Activity activity) {
        // android  P 以上有标准 API 来判断是否有刘海屏
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            View decorView = activity.getWindow().getDecorView();
            WindowInsets windowInsets = decorView.getRootWindowInsets();
            if (windowInsets != null) {
                DisplayCutout displayCutout = windowInsets.getDisplayCutout();
                if (displayCutout != null) {
                    List<Rect> rects = displayCutout.getBoundingRects();

                    for (Rect rect : rects) {
                        Log.e("notch", "cutout.getSafeInsetTop():" + displayCutout.getSafeInsetTop()
                                + ", cutout.getSafeInsetBottom():" + displayCutout.getSafeInsetBottom()
                                + ", cutout.getSafeInsetLeft():" + displayCutout.getSafeInsetLeft()
                                + ", cutout.getSafeInsetRight():" + displayCutout.getSafeInsetRight()
                                + ", cutout.rects:" + rect
                        );
                    }

                    int screenTopMargin = displayCutout.getSafeInsetTop();
                    int screenBottomMargin = displayCutout.getSafeInsetBottom();

                    //通过判断是否存在rects来确定是否刘海屏手机
                    if (rects.size() > 0) {
                        return true;
                    }
                }
            }
        }
        // 通过其他方式判断是否有刘海屏  目前官方提供有开发文档的就 小米,vivo,华为(荣耀),oppo
        String manufacturer = Build.MANUFACTURER;
        if (StringUtils.isEmpty(manufacturer)) {
            return false;
        } else if (manufacturer.equalsIgnoreCase("HUAWEI")) {
            return hasNotchHw(activity);
        } else if (manufacturer.equalsIgnoreCase("xiaomi")) {
            return hasNotchXiaoMi(activity);
        } else if(manufacturer.equalsIgnoreCase("oppo")||manufacturer.equalsIgnoreCase("realme")) {//这里是除oppo以外的品牌手机,这里暂时没有这个手机,但也加上是评论区的伙伴验证的
            return hasNotchOPPO(activity);
        } else if (manufacturer.equalsIgnoreCase("vivo")) {
            return hasNotchVIVO(activity);
        } else {
            return false;
        }
    }

    /**
     * 获取华为刘海的高
     *
     * @param context
     * @return
     */
    public static int getNotchSizeAtHuawei(Context context) {
        int[] ret = new int[]{0, 0};
        try {
            ClassLoader cl = context.getClassLoader();
            Class<?> HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = HwNotchSizeUtil.getMethod("getNotchSize");
            ret = (int[]) get.invoke(HwNotchSizeUtil);

        } catch (ClassNotFoundException e) {
            Log.e("NotchScreenUtil", "getNotchSize ClassNotFoundException");
        } catch (NoSuchMethodException e) {
            Log.e("NotchScreenUtil", "getNotchSize NoSuchMethodException");
        } catch (Exception e) {
            Log.e("NotchScreenUtil", "getNotchSize Exception");
        }
        return ret[1];
    }


    /**
     * 判断vivo是否有刘海屏
     * https://swsdl.vivo.com.cn/appstore/developer/uploadfile/20180328/20180328152252602.pdf
     *
     * @param activity
     * @return
     */
    private static boolean hasNotchVIVO(Activity activity) {
        try {
            @SuppressLint("PrivateApi") Class<?> c = Class.forName("android.util.FtFeature");
            Method get = c.getMethod("isFeatureSupport", int.class);
            return (boolean) (get.invoke(c, 0x20));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 判断oppo是否有刘海屏
     * https://open.oppomobile.com/wiki/doc#id=10159
     *
     * @param activity
     * @return
     */
    private static boolean hasNotchOPPO(Activity activity) {
        return activity.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
    }

    /**
     * 判断xiaomi是否有刘海屏
     * https://dev.mi.com/console/doc/detail?pId=1293
     *
     * @param activity
     * @return
     */
    private static boolean hasNotchXiaoMi(Activity activity) {
        try {
            @SuppressLint("PrivateApi") Class<?> c = Class.forName("android.os.SystemProperties");
            Method get = c.getMethod("getInt", String.class, int.class);
            return (int) (get.invoke(c, "ro.miui.notch", 0)) == 1;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 判断华为是否有刘海屏
     * https://devcenter-test.huawei.com/consumer/cn/devservice/doc/50114
     *
     * @param activity
     * @return
     */
    private static boolean hasNotchHw(Activity activity) {

        try {
            ClassLoader cl = activity.getClassLoader();
            Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
            return (boolean) get.invoke(HwNotchSizeUtil);
        } catch (Exception e) {
            return false;
        }
    }



版权声明:本文为qq_34900897原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。