Android刘海屏高度获取(小米,华为,荣耀,vivo,OPPO,三星,锤子等主流机型),用来计算沉浸式适配。

1.第一步 首先判断Android手机是否是有刘海

判断小米手机是否有刘海屏

/**
 * 小米刘海屏判断
 * @return 0 if it is not notch ; return 1 means notch
 * @throws IllegalArgumentException if the key exceeds 32 characters
 */
public static boolean hasNotchAtXiaoMi() {
        return getInt("ro.miui.notch") == 1;
}
public static int getInt(String key) {
        int result = 0;
        if (android.os.Build.MANUFACTURER.equalsIgnoreCase("Xiaomi")) {
            try {
                ClassLoader classLoader = Application.getInstance().getClassLoader();
                @SuppressWarnings("rawtypes")
                Class SystemProperties = classLoader.loadClass("android.os.SystemProperties");
                //参数类型
                @SuppressWarnings("rawtypes")
                Class[] paramTypes = new Class[2];
                paramTypes[0] = String.class;
                paramTypes[1] = int.class;
                Method getInt = SystemProperties.getMethod("getInt", paramTypes);
                //参数
                Object[] params = new Object[2];
                params[0] = new String(key);
                params[1] = new Integer(0);
                result = (Integer) getInt.invoke(SystemProperties, params);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
}

判断华为和荣耀手机是否有刘海屏

/**
 * 华为刘海屏判断
 * @return
 */
public static boolean hasNotchAtHuawei() {
        boolean ret = false;
        try {
            ClassLoader classLoader = Application.getInstance().getClassLoader();
            Class HwNotchSizeUtil = classLoader.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
            ret = (boolean) get.invoke(HwNotchSizeUtil);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
}

判断OPPO手机是否有刘海屏

/**
 * OPPO刘海屏判断
 * @return
 */
public static boolean hasNotchAtOPPO() {
        return Application.getInstance().getPackageManager()
                .hasSystemFeature("com.oppo.feature.screen.heteromorphism");
}

判断VIVO手机是否有刘海屏

/**
 * VIVO刘海屏判断
 * @return
 */
public static boolean hasNotchAtVivo() {
        boolean ret = false;
        try {
            ClassLoader classLoader = Application.getInstance().getClassLoader();
            Class FtFeature = classLoader.loadClass("android.util.FtFeature");
            Method method = FtFeature.getMethod("isFeatureSupport", int.class);
            ret = (boolean) method.invoke(FtFeature, VIVO_NOTCH);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
}

判断三星手机是否有刘海屏

/**
* 判断三星手机是否有刘海屏
* @return
*/
private static boolean hasNotchSamsung() {
        if (android.os.Build.MANUFACTURER.equalsIgnoreCase("samsung")) {
            try {
                final Resources res = Application.getInstance().getResources();
                final int resId = res.getIdentifier("config_mainBuiltInDisplayCutout", "string", "android");
                final String spec = resId > 0 ? res.getString(resId) : null;
                return spec != null && !TextUtils.isEmpty(spec);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
}

其他Android手机是否有刘海屏 通过Google Android SDK的方法进行判断

/**
 * @param activity
* @return
*/
private static boolean isOtherBrandHasNotch(Activity activity) {
        if (activity != null && activity.getWindow() != null) {
            View decorView = activity.getWindow().getDecorView();
            if ((Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)) {
                WindowInsets windowInsets = decorView.getRootWindowInsets();
                if (windowInsets != null) {
                    if ((Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P)) {
                        DisplayCutout displayCutout = windowInsets.getDisplayCutout();
                        if (displayCutout != null) {
                            List rects = displayCutout.getBoundingRects();
                            if (rects != null && rects.size() > 0) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
   return false;
}

综合上边所有的方法

/**
 * 是否是刘海或是钻孔屏幕 全局只取一次
 * @return
 */
 public static boolean hasNotch(Activity activity) {
        if (!hasExecuteNotch) {
            if (hasNotchAtXiaoMi() || hasNotchAtHuawei() || hasNotchAtOPPO()
                    || hasNotchAtVivo() || hasNotchSamsung() || isOtherBrandHasNotch(activity)) {
                isNotch = true;
            } else {
                isNotch = false;
            }
            hasExecuteNotch = true;
        }
        return isNotch;
}

2.如果是刘海屏获取刘海的高度

/**
 * 获取刘海高度
 */
public static int getNotchHeight(Activity activity) {
        String manufacturer = android.os.Build.MANUFACTURER.toLowerCase();
        if (hasNotch(activity)) {
            //有刘海才获取高度 否则默认刘海高度是0
            if (manufacturer.equalsIgnoreCase("xiaomi")) {
                notchHeight = getSysStatusBarHeight();//小米刘海会比状态栏小 直接获取状态栏高度
            } else if (manufacturer.equalsIgnoreCase("huawei") || manufacturer.equalsIgnoreCase("honour")) {
                notchHeight = getNotchSizeAtHuaWei();
            } else if (manufacturer.equalsIgnoreCase("vivo")) {
                //VIVO是32dp
                notchHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        32, Application.getInstance().getResources().getDisplayMetrics());
            } else if (manufacturer.equalsIgnoreCase("oppo")) {
                notchHeight = 80;//oppo当时是固定数值
            } else if (android.os.Build.MANUFACTURER.equalsIgnoreCase("smartisan")) {
                notchHeight = 82;//当时锤子PDF文档上是固定数值
            }  else {
                //其他品牌手机
                if (activity != null && activity.getWindow() != null) {
                    View decorView = activity.getWindow().getDecorView();
                    if ((Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)) {
                        WindowInsets windowInsets = decorView.getRootWindowInsets();
                        if (windowInsets != null) {
                            if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)) {
                                DisplayCutout displayCutout = windowInsets.getDisplayCutout();
                                if (displayCutout != null) {
                                    List rects = displayCutout.getBoundingRects();
                                    if (rects != null && rects.size() > 1) {
                                        if (rects.get(0) != null) {
                                            notchHeight = rects.get(0).bottom;
                                            return notchHeight;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return notchHeight;
        }
        return 0;
    }

获取华为&荣耀手机刘海屏高度

/**
     * 华为获取刘海高度
     * 获取刘海尺寸:width、height
     * int[0]值为刘海宽度 int[1]值为刘海高度
*/
public static int getNotchSizeAtHuaWei() {
        int height = 0;
        try {
            ClassLoader cl = Application.getInstance().getClassLoader();
            Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = HwNotchSizeUtil.getMethod("getNotchSize");
            int[] ret = (int[]) get.invoke(HwNotchSizeUtil);
            height = ret[1];
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return height;
}

3.状态栏和刘海高度中获取更大的值 作为顶部适配高度 每次APP启动只获取一次

public static int getStatusBarHeight(Activity activity) {
        if (statusBarHeight == 0) {
            int height = getSysStatusBarHeight();
            int notchHeight = ScreenUtil.getNotchHeight(activity);
            statusBarHeight = Math.max(height, notchHeight);
        }
        return statusBarHeight;
}

获取手机状态栏高度

/**
 * 获得手机状态栏高度
 * @return
 */
public static int getSysStatusBarHeight() {
        int result = 0;
        Resources resources = Application.getInstance().getResources();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = resources.getDimensionPixelSize(resourceId);
        }
        if (result == 0) {
            result = resources.getDimensionPixelSize(R.dimen.default_48PX);
        }
        return result;
    }

以上代码已经上线,如有适配更新请各位指正。!_!

你可能感兴趣的:(Android刘海屏高度获取(小米,华为,荣耀,vivo,OPPO,三星,锤子等主流机型),用来计算沉浸式适配。)