如何获取顶部带Notch的屏幕尺寸?适配Android P及更早版本设备
我来给你梳理下具体的解决方案,分两种场景(Android P及以上、Pre-P设备)来处理,毕竟Android P之前官方没有统一的刘海适配标准,得兼容各家厂商的自定义实现:
解决方案:分Android P及以上、Pre-P设备适配
一、Android P(API 28+):官方标准适配
Android 9.0开始官方引入了DisplayCutout类来统一处理刘海/挖孔屏,你可以通过以下步骤适配:
获取安全区域(Safe Area)尺寸
别再直接用getRealSize拿全屏幕尺寸了,应该获取排除刘海区域的安全区域,这样游戏内容就不会跑到刘海里或者超出屏幕:// 可以在Activity的onWindowFocusChanged或者View的onAttachedToWindow中调用 View decorView = getWindow().getDecorView(); decorView.setOnApplyWindowInsetsListener((v, insets) -> { DisplayCutout cutout = insets.getDisplayCutout(); if (cutout != null) { // 获取刘海四周的安全边距:top/left/right/bottom int safeInsetTop = cutout.getSafeInsetTop(); int safeInsetBottom = cutout.getSafeInsetBottom(); int safeInsetLeft = cutout.getSafeInsetLeft(); int safeInsetRight = cutout.getSafeInsetRight(); // 计算安全区域的实际可用尺寸 int safeWidth = screenSize.x - safeInsetLeft - safeInsetRight; int safeHeight = screenSize.y - safeInsetTop - safeInsetBottom; // 用safeWidth和safeHeight设置游戏视图的渲染区域,或者调整内容布局 } return insets.consumeSystemWindowInsets(); });设置窗口刘海模式
在AndroidManifest.xml中给游戏Activity添加主题属性,控制内容是否允许延伸到刘海区域:<activity android:name=".YourGameActivity"> <meta-data android:name="android.window.layoutInDisplayCutoutMode" android:value="never" /> <!-- 可选值:default/shortEdges/never --> </activity>never:内容完全避开刘海区域,安全区域就是排除刘海的可用区域shortEdges:允许内容延伸到刘海所在的短边(比如竖屏时的顶部刘海)default:系统默认行为,通常允许内容延伸到刘海区域
二、Pre-P设备(Android 8/8.1等):厂商自定义适配
Android 9之前没有官方刘海API,需要针对主流厂商(华为、小米、OPPO、vivo)分别处理,核心是通过反射或厂商提供的API获取刘海尺寸,再手动调整游戏内容的显示区域:
华为设备(比如你的P20)
华为提供了自定义的刘海检测和尺寸获取方法,用反射就能实现:
// 判断设备是否有刘海 public static boolean hasNotchInScreen(Context context) { boolean hasNotch = false; try { ClassLoader cl = context.getClassLoader(); Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil"); Method method = HwNotchSizeUtil.getMethod("hasNotchInScreen"); hasNotch = (boolean) method.invoke(HwNotchSizeUtil); } catch (Exception e) { e.printStackTrace(); } return hasNotch; } // 获取刘海尺寸(返回int数组,[0]是宽度,[1]是高度) public static int[] getNotchSize(Context context) { int[] notchSize = new int[2]; try { ClassLoader cl = context.getClassLoader(); Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil"); Method method = HwNotchSizeUtil.getMethod("getNotchSize"); notchSize = (int[]) method.invoke(HwNotchSizeUtil); } catch (Exception e) { e.printStackTrace(); } return notchSize; }
拿到刘海高度后,给游戏视图顶部留出对应高度的padding,或者直接把游戏的渲染区域从刘海下方开始计算。
小米设备
小米的刘海适配可以通过自定义WindowManager参数和反射实现:
// 判断是否有刘海 public static boolean hasNotch(Context context) { boolean hasNotch = false; try { ClassLoader cl = context.getClassLoader(); Class MiuiFeature = cl.loadClass("android.os.SystemProperties"); Method get = MiuiFeature.getMethod("getInt", String.class, int.class); hasNotch = (int) get.invoke(MiuiFeature, "ro.miui.notch", 0) == 1; } catch (Exception e) { e.printStackTrace(); } return hasNotch; } // 设置窗口允许延伸到刘海区域(可选) WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; getWindow().setAttributes(lp);
OPPO设备
OPPO的刘海适配可以用系统特性检测和反射:
// 判断是否有刘海 public static boolean hasNotch(Context context) { return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism"); } // 获取刘海尺寸 public static int[] getNotchSize(Context context) { int[] notchSize = new int[2]; try { ClassLoader cl = context.getClassLoader(); Class OppoDisplay = cl.loadClass("com.oppo.util.OppoDisplayCutout"); Method method = OppoDisplay.getMethod("getRealNotchSize"); notchSize = (int[]) method.invoke(OppoDisplay); } catch (Exception e) { e.printStackTrace(); } return notchSize; }
通用优化建议
- 不管用哪种方案,都不要直接依赖
getRealSize返回的全屏幕尺寸,始终基于安全区域来布局游戏内容,这是避免内容超出屏幕或被刘海遮挡的核心。 - 对于全屏游戏,建议给游戏视图添加对应刘海高度的顶部padding,或者将游戏的渲染区域直接限制在安全区域内,保证所有核心内容都能正常显示。
内容的提问来源于stack exchange,提问作者Javasamurai
相关产品推荐
相关产品推荐

