Android刘海屏适配及view被摄像头遮挡动态改变位置

刘海屏适配及view被摄像头遮挡动态改变位置
目前市面上的刘海屏、水滴屏、挖孔屏越来越多,作为移动开发者来说,这并不是一件好事,越来越多异形屏的出现意味着我们需要投入大量的经历在屏幕适配上,本文总结了当下主流手机的屏幕适配方式(华为、vivo、oppo、小米)以及判断view是否被摄像头遮挡,去动态改变view的位置 。
一.P及以上
谷歌官方从 P开始给开发者提供了刘海屏相关的API,可以通过直接调用API来进行刘海屏的适配处理 。通过类可以获得安全区域的范围以及刘海区域(官方的叫法是缺口)的信息,只有API Level在28及以上才可以调用 。
1. 判断是否是异形屏
/*** Android P异形屏判断** @param activity activity* @return 是否是异形屏*/public static boolean isSpecialScreen(Activity activity) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {final View decorView = activity.getWindow().getDecorView();if (decorView != null) {WindowInsets windowInsets = decorView.getRootWindowInsets();if (windowInsets != null) {DisplayCutout cutoutDisp = windowInsets.getDisplayCutout();if(cutoutDisp != null) {displayCutout = cutoutDisp;return true;}}}}return false;}
2. 获取异形屏的刘海高度
/*** 9.0以上手机,获取异形屏的刘海高度** @return 获取异形屏的刘海高度*/@RequiresApi(28)private static int getNotchHeightFromP() {int notchHeight = 0;if (SwanApp.get() == null || SwanApp.get().getActivity() == null) {return notchHeight;}try {View view = SwanApp.get().getActivity().getWindow().getDecorView();WindowInsets windowInsets = view.getRootWindowInsets();if (windowInsets == null) {return notchHeight;}DisplayCutout displayCutout = windowInsets.getDisplayCutout();if (displayCutout == null) {return notchHeight;}notchHeight = displayCutout.getSafeInsetTop();if (DEBUG) {Log.d(TAG, "刘海屏高度:" + notchHeight);}} catch (Exception e) {if (DEBUG) {Log.w(TAG, e);}}return notchHeight;}
二.P以下
对于 P以下的手机,我们可以通过各个厂商提供的适配方案来进行适配 。
1. 华为适配方案
/*** 判断华为是否有刘海屏** @param context Context* @return hasNotch 是否有刘海屏*/private static boolean hasNotchAtHuawei(@NonNull Context context) {boolean ret = false;try {ClassLoader classLoader = context.getClassLoader();Class HwNotchSizeUtil = classLoader.loadClass("com.huawei.android.util.HwNotchSizeUtil");Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");ret = (boolean) get.invoke(HwNotchSizeUtil);} catch (Exception e) {if (DEBUG) {e.printStackTrace();}}return ret;}

Android刘海屏适配及view被摄像头遮挡动态改变位置

文章插图
2. VIVO适配方案
/*** 判断VIVO是否有刘海屏* * 0x00000020表示是否有凹槽;* 0x00000008表示是否有圆角 。** @param context Context* @return hasNotch 是否有刘海屏*/private static boolean hasNotchAtVivo(@NonNull Context context) {boolean ret = false;try {ClassLoader classLoader = context.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) {if (DEBUG) {e.printStackTrace();}}return ret;}
3. 小米适配方案
/*** 判断MIUI是否有刘海屏** @param context Context* @return 是否有刘海屏*/private static boolean hasNotchAtMiui(@NonNull Context context) {boolean ret = false;try {ClassLoader classLoader = context.getClassLoader();Class SystemProperties = classLoader.loadClass("android.os.SystemProperties");Method getInt = SystemProperties.getMethod("getInt", String.class, int.class);ret = (Integer) getInt.invoke(SystemProperties, "ro.miui.notch", 0) == 1;} catch (Exception e) {if (DEBUG) {e.printStackTrace();}}return ret;}
4. OPPO适配方案