Android 9.0(Pie, APILevel 28)开始提供了统一的获取异型屏数据的接口,Android 9.0之前的系统则需要根据各个厂商的SDK来单独获取了。本文主要罗列了华为、小米、OPPO & VIVO四家厂商的异形屏SDK用法。
如果需要华为手机显示非安全区域,需要应用的AndroidManifest.xml中增加meta-data notch_support。此属性不仅可以针对Application生效,也可以对Activity配置生效。
layoutInDisplayCutoutMode
Android 还允许您控制是否在刘海区域内显示内容。窗口布局属性 layoutInDisplayCutoutMode 控制您的内容如何呈现在刘海区域中。您可以将 layoutInDisplayCutoutMode
设为以下某个值:
layoutInDisplayCutoutMode 更多内容可以访问官方文章 https://developer.android.com/guide/topics/display-cutout
private static void androidPieScreenAdaptation(Context curContext) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
View decorView = activity.getWindow().getDecorView();
WindowInsets windowInsets = decorView.getRootWindowInsets();
if (windowInsets != null) {
// 当全屏顶部显示黑边时,getDisplayCutout()返回为null
DisplayCutout displayCutout = windowInsets.getDisplayCutout();
if(displayCutout != null) {
//通过判断是否存在rects来确定是否刘海屏手机
List rects = displayCutout.getBoundingRects();
if (rects != null && rects.size() > 0)
Log.d(LogTag, "异形屏手机!");
Log.d(LogTag, "安全区域距离屏幕左边的距离 SafeInsetLeft:" + displayCutout.getSafeInsetLeft());
Log.d(LogTag, "安全区域距离屏幕右部的距离 SafeInsetRight:" + displayCutout.getSafeInsetRight());
Log.d(LogTag, "安全区域距离屏幕顶部的距离 SafeInsetTop:" + displayCutout.getSafeInsetTop());
Log.d(LogTag, "安全区域距离屏幕底部的距离 SafeInsetBottom:" + displayCutout.getSafeInsetBottom());
}
}
}
}
/*
* 华为手机异形屏数据获取
*/
private static void hasNotchInScreen_huawei(Context context) {
try {
boolean isNotch = false; // 是否未异型屏
int[] notchSize; // 异形屏区域大小
ClassLoader cl = context.getClassLoader();
Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
Object obj = get.invoke(HwNotchSizeUtil);
if (obj != null)
isNotch = obj.toString().toUpperCase().equals("TRUE") ? true : false;
if (isNotch) {
get = HwNotchSizeUtil.getMethod("getNotchSize");
notchSize = (int[]) get.invoke(HwNotchSizeUtil);
Log.d(LogTag, "异形屏 H = " + notchSize[0]);
Log.d(LogTag, "异形屏 W = " + notchSize[1]);
}
} catch (ClassNotFoundException e) {
Log.d("error", "error getNotchSize ClassNotFoundException");
} catch (NoSuchMethodException e) {
Log.d("error", "error getNotchSize NoSuchMethodException");
} catch (Exception e) {
Log.d("error", "error getNotchSize Exception:" + e.getMessage());
} finally {
}
}
/*
小米手机异形屏数据获取
*/
private static void hasNotchInScreen_Xiaomi(Context context) {
try {
boolean isNotch = false; // 是否异型屏
int noutchSize; // 异形屏尺寸
ClassLoader cl = context.getClassLoader();
Class systemPro = cl.loadClass("android.os.SystemProperties");
Method get = systemPro.getMethod("get", String.class);
Object obj = (get.invoke(systemPro, "ro.miui.notch"));
if (obj != null) {
if (obj.toString().contains("1"))
isNotch = true;
if(isNotch) {
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
noutchSize = context.getResources().getDimensionPixelSize(resourceId);
}
}
} catch (ClassNotFoundException e) {
SDKUtil.LogInfo(LogTag, "error hasNotchInScreen_Xiaomi ClassNotFoundException");
} catch (NoSuchMethodException e) {
SDKUtil.LogInfo(LogTag, "error hasNotchInScreen_Xiaomi NoSuchMethodException");
} catch (Exception e) {
SDKUtil.LogInfo(LogTag, "error hasNotchInScreen_Xiaomi Exception:" + e.getMessage());
} finally {
}
}
/*
oppo 异形屏数据获取,厂商sdk只支持获取是否未异型屏,无法获取具体尺寸
*/
private static void oppoScreenAdaptation(Context context) {
if (context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism")) {
Log.d("", "异形屏");
} else {
Log.d("", "非异形屏");
}
}
/*
vivo 异形屏数据获取,厂商sdk只支持获取是否未异型屏,无法获取具体尺寸
*/
private static void hasNotchInScreen_Vivo(Context context) {
try {
boolean isNotch = false; // 是否异型屏
ClassLoader cl = context.getClassLoader();
Class FtFeature = cl.loadClass("android.util.FtFeature");
Method get = FtFeature.getMethod("isFeatureSupport", int.class);
Object obj = get.invoke(FtFeature, NOTCH_IN_SCREEN_VOIO);
if (obj != null)
isNotch = obj.toString().toUpperCase().equals("TRUE");
} catch (ClassNotFoundException e) {
SDKUtil.LogInfo(LogTag, "hasNotchInScreen ClassNotFoundException");
} catch (NoSuchMethodException e) {
SDKUtil.LogInfo(LogTag, "hasNotchInScreen NoSuchMethodException");
} catch (Exception e) {
SDKUtil.LogInfo(LogTag, "hasNotchInScreen Exception");
}
}
Untiy2018及以上的版本,如果需要刘海区域内显示内容,需要将PlayerSetting中的Render outside safe area项勾选上。