Android 检测手机是否是异形屏,刘海屏,水滴屏,挖孔屏

全面屏适配请阅读本人另外一篇博客:

https://blog.csdn.net/zhao8856234/article/details/117744924?spm=1001.2014.3001.5501

直接上工具类,复制使用即可:

public class NotchUtil {
    private static final String SP_NAME = "MY_NOTCH_SP";//保存异形屏Name
    private static final String KEY_IS_NOTCH_SCREEN = "KEY_IS_NOTCH_SCREEN";//是否是异形屏KEY

    /**
     * 保存当前手机是否是异形屏
     *
     * @param isNotchScreen 是否是异形屏(刘海屏,水滴屏,挖孔屏等)
     */
    public static void saveScreen(Context context, boolean isNotchScreen) {
        SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = sp.edit();
        if (!sp.contains(KEY_IS_NOTCH_SCREEN)) {//不存在的时候保存
            edit.putBoolean(KEY_IS_NOTCH_SCREEN, isNotchScreen);
        } else if (sp.contains(KEY_IS_NOTCH_SCREEN) && !sp.getBoolean(KEY_IS_NOTCH_SCREEN, false)) {
            //当这个值存在并且是false的时候也保存
            edit.putBoolean(KEY_IS_NOTCH_SCREEN, isNotchScreen);
        }
        //当这个值存在并且为true的时候不去覆盖数据.
        edit.commit();
    }

    /**
     * 获取保存在本地的屏幕类型,是否是异形屏(刘海屏,水滴屏,挖孔屏等)
     */
    public static boolean getScreenType(Context context) {
        return context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE).getBoolean(KEY_IS_NOTCH_SCREEN, false);
    }


    /**
     * 判断是否是8.0系统之后的异形屏(刘海屏,水滴屏,挖孔屏等)
     * 必须在Activity的onAttachedToWindow()方法中才会生效,其他地方windowInsets为 null
     * onCreate->onStart->onResume->onAttachedToWindow
     */
    public static boolean IsNotchScreen(Context context, WindowInsets windowInsets) {
        if (Build.VERSION.SDK_INT >= 26) {
            if (isAndroidPNotchScreen(windowInsets) || hasNotchInScreenAtVivo(context) || hasNotchInScreenAtOppo(context)
                    || hasNotchInScreenAtHuawei(context) || hasNotchInScreenAtMI()) { //TODO 各种品牌
                return true;
            }
        }
        return false;
    }


     /**
     * Android P 异形屏判断
     *
     * @param windowInsets 必须使用控件的setOnApplyWindowInsetsListener()接口回调方法中的才或者在Activity的
     *                     onAttachedToWindow()方法中调用getWindow().getDecorView().getRootWindowInsets();
     *                     其他地方获取会直接为空
     */
    @SuppressLint("NewApi")
    public static boolean isAndroidPNotchScreen(WindowInsets windowInsets) {
        boolean isNotchScreen = false;
        if (PlatformUtils.isAndroidP() && null != windowInsets) {
            DisplayCutout cutout = windowInsets.getDisplayCutout();
            if (cutout != null) {
                List<Rect> rects = cutout.getBoundingRects();
                if (rects != null && rects.size() > 0) {
                    isNotchScreen = true;
                }
            }
        }
        return isNotchScreen;
    }

    /**
     * 判断是否华为异形屏
     */
    public static boolean hasNotchInScreenAtHuawei(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) {
            PlatformLog.ee("hasNotchInScreenAtHuawei()-> ClassNotFoundException");
        } catch (NoSuchMethodException e) {
            PlatformLog.ee("hasNotchInScreenAtHuawei()-> NoSuchMethodException");
        } catch (Exception e) {
            PlatformLog.ee("hasNotchInScreenAtHuawei()-> Exception");
        } finally {
            PlatformLog.e("hasNotchInScreenAtHuawei()-> ClassNotFoundException");
            return ret;
        }
    }

    /**
     * 获取华为O版本异形屏宽高
     */
    public static int[] getNotchSizeForHuawei(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) {
            PlatformLog.ee("HUAWEI-getNotchSize()-> ClassNotFoundException");
        } catch (NoSuchMethodException e) {
            PlatformLog.ee("HUAWEI-getNotchSize()-> NoSuchMethodException");
        } catch (Exception e) {
            PlatformLog.ee("HUAWEI-getNotchSize()-> Exception");
        } finally {
            return ret;
        }
    }

    /**
     * 判断oppo 机型是否异形屏
     */
    public static boolean hasNotchInScreenAtOppo(Context context) {
        return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
    }

    public static String getNotchOppoProperty() {
        String value = "";
        try {
            Class<?> cls = Class.forName("android.os.SystemProperties");
            Method hideMethod = cls.getMethod("get", String.class);
            Object object = cls.newInstance();
            value = (String) hideMethod.invoke(object, "ro.oppo.screen.heteromorphism");
        } catch (ClassNotFoundException e) {
            PlatformLog.ee("getNotchOppoProperty()->get error() ", e.getMessage());
        } catch (NoSuchMethodException e) {
            PlatformLog.ee("getNotchOppoProperty()->get error() ", e.getMessage());
        } catch (InstantiationException e) {
            PlatformLog.ee("getNotchOppoProperty()->get error() ", e.getMessage());
        } catch (IllegalAccessException e) {
            PlatformLog.ee("getNotchOppoProperty()->get error() ", e.getMessage());
        } catch (IllegalArgumentException e) {
            PlatformLog.ee("getNotchOppoProperty()->get error() ", e.getMessage());
        } catch (InvocationTargetException e) {
            PlatformLog.ee("getNotchOppoProperty()->get error() ", e.getMessage());
        }
        return value;
    }

    /**
     * 判断vivo机型是否异形屏
     */
    public static final int NOTCH_IN_SCREEN_VOIO = 0x00000020;//是否有凹槽
    public static final int ROUNDED_IN_SCREEN_VOIO = 0x00000008;//是否有圆角

    public static boolean hasNotchInScreenAtVivo(Context context) {
        boolean ret = false;
        try {
            ClassLoader cl = context.getClassLoader();
            Class FtFeature = cl.loadClass("android.util.FtFeature");
            Method get = FtFeature.getMethod("isFeatureSupport", int.class);
            ret = (boolean) get.invoke(FtFeature, NOTCH_IN_SCREEN_VOIO);

        } catch (ClassNotFoundException e) {
            PlatformLog.ee("hasNotchInScreenAtVivo()-> ClassNotFoundException");
        } catch (NoSuchMethodException e) {
            PlatformLog.ee("hasNotchInScreenAtVivo()-> NoSuchMethodException");
        } catch (Exception e) {
            PlatformLog.ee("hasNotchInScreenAtVivo()-> Exception");
        } finally {
            return ret;
        }
    }

    /**
     * 判断小米机型是否异形屏
     */
    private static Method getBooleanMethod = null;

    public static boolean hasNotchInScreenAtMI() {
        try {
            if (getBooleanMethod == null) {
                getBooleanMethod = Class.forName("android.os.SystemProperties").getMethod("getBoolean", String.class, boolean.class);
            }
            //Log.i(TAG,"getBoolean:"+getBooleanMethod.invoke(null, key, def));
            return (Boolean) getBooleanMethod.invoke(null, "ro.miui.notch", false);
        } catch (Exception e) {
            return false;
        }
    }



}

调用方法:

1. Activity调用:

/**
     * 生命周期 onCreate->onStart->onResume->onAttachedToWindow
     * 判断是否是异形屏,必须在此方法
     */
    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (Build.VERSION.SDK_INT >= 23) {
            boolean isNotchScreen = NotchUtil.IsNotchScreen(this, getWindow().getDecorView().getRootWindowInsets());
           
            NotchUtil.saveScreen(this, isNotchScreen);
        }
    }

2. 控件调用:

 public static void setNotchScreenParentLayout(final Context context, final View parentLayout) {
        //异形屏 刘海屏从安卓8.0系统开始推出
        if (null != context && null != parentLayout && Build.VERSION.SDK_INT >= 26) {
            //设置异形屏的安全区域,避免遮挡内容
            parentLayout.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
                @Override
                public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
                    boolean isNotchScreen = NotchUtil.IsNotchScreen(context, windowInsets);
                   
                    if (isNotchScreen && null != windowInsets) {
                        parentLayout.setPadding(0, 0, 0, 0);
                        if (Build.VERSION.SDK_INT >= 28 && null != windowInsets.getDisplayCutout()) {
                            DisplayCutout cutout = windowInsets.getDisplayCutout();
                            if (cutout != null) {
                                List<Rect> rects = cutout.getBoundingRects();
                                if (rects != null && rects.size() > 0) {
                                    PlatformLog.e("异形屏->安卓9.0之后系统,间距左" + cutout.getSafeInsetLeft() +
                                            ",上:" + cutout.getSafeInsetTop() + ",右:" + cutout.getSafeInsetRight() + ",下:" + cutout.getSafeInsetBottom());
                                    parentLayout.setPadding(cutout.getSafeInsetLeft(), cutout.getSafeInsetTop(),
                                            cutout.getSafeInsetRight(), cutout.getSafeInsetBottom());
                                }
                            }
                        }
                    }
                    return windowInsets;
                }
            });
        }
    }

猜你喜欢

转载自blog.csdn.net/zhao8856234/article/details/117747273