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;
}
以上代码已经上线,如有适配更新请各位指正。!_!