全面屏适配请阅读本人另外一篇博客:
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";//保存异形屏Nameprivate 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* 判断是否是异形屏,必须在此方法*/@Overridepublic 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() {@Overridepublic 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;}});}}