Android全面屏适配核心方案
沉浸式状态栏适配
// 方式1:使用SystemUI控制
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
window.decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
)
}
// 方式2:Android 5.0+透明状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.apply {
clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
statusBarColor = Color.TRANSPARENT
decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
)
}
}
刘海屏/挖孔屏适配
// 检查是否支持刘海屏
private fun isNotchSupported(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
}
// 获取刘海屏安全区域
private fun getDisplayCutoutSafeInsets(): Rect {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val displayCutout = window.decorView.rootWindowInsets?.displayCutout
displayCutout?.safeInsetTop ?: 0
displayCutout?.safeInsetBottom ?: 0
displayCutout?.safeInsetLeft ?: 0
displayCutout?.safeInsetRight ?: 0
Rect(left, top, right, bottom)
} else {
Rect(0, 0, 0, 0)
}
}
// 设置刘海屏模式
private fun setDisplayCutoutMode() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val params = window.attributes
// 模式选择:
// LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT - 默认
// LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES - 短边使用
// LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER - 从不使用
params.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
window.attributes = params
}
}
全面屏手势导航适配
// 获取手势导航栏高度
private fun getNavigationBarHeight(): Int {
val resources = resources
val resourceId = resources.getIdentifier(
"navigation_bar_height",
"dimen",
"android"
)
return if (resourceId > 0) {
resources.getDimensionPixelSize(resourceId)
} else 0
}
// 处理手势冲突
private fun handleGestureConflict() {
window.decorView.setOnApplyWindowInsetsListener { view, insets ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val systemGestures = insets.getInsets(
WindowInsets.Type.systemGestures()
)
// 调整布局避免手势冲突
updateLayoutForSystemGestures(systemGestures)
}
insets
}
}
XML布局适配策略
使用 fitsSystemWindows
<!-- 方式1:在根布局设置 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- 内容区域 -->
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- 方式2:在 CoordinatorLayout 中使用 -->
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<!-- Toolbar -->
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
安全区域插入适配
<!-- 使用 padding 适配安全区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="@dimen/status_bar_height"
android:paddingBottom="@dimen/navigation_bar_height"
android:orientation="vertical">
<!-- 实际内容 -->
</LinearLayout>
Jetpack Compose全面屏适配
@Composable
fun FullScreenContent() {
// 获取WindowInsets
val windowInsets = rememberWindowInsets()
Box(
modifier = Modifier
.fillMaxSize()
.windowInsetsPadding(windowInsets.statusBars)
) {
// 主内容
Column(
modifier = Modifier
.fillMaxSize()
.padding(bottom = windowInsets.navigationBars.asPaddingValues().calculateBottomPadding())
) {
// 页面内容
}
}
}
// 或者使用 Accompanist Insets
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun FullScreenWithInsets() {
Scaffold(
modifier = Modifier
.fillMaxSize()
.statusBarsPadding()
.navigationBarsPadding()
) { paddingValues ->
// 使用 paddingValues 调整内容
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
// 列表内容
}
}
}
配置文件设置
AndroidManifest.xml 配置
<application
android:theme="@style/AppTheme">
<!-- 支持最大屏幕比例(针对全面屏) -->
<meta-data
android:name="android.max_aspect"
android:value="2.4" />
<!-- 适配刘海屏 -->
<meta-data
android:name="android.notch_support"
android:value="true" />
</application>
<!-- 或在Activity中声明 -->
<activity
android:name=".MainActivity"
android:theme="@style/FullScreenTheme"
android:windowSoftInputMode="adjustResize"
android:screenOrientation="portrait"
android:resizeableActivity="true">
<!-- 声明支持刘海屏 -->
<meta-data
android:name="android.notch_support"
android:value="true" />
</activity>
styles.xml 样式定义
<!-- 全面屏主题 -->
<style name="AppTheme.FullScreen" parent="Theme.AppCompat.Light.NoActionBar">
<!-- 状态栏透明 -->
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<!-- 适配刘海屏 -->
<item name="android:windowLayoutInDisplayCutoutMode">
shortEdges
</item>
<!-- 隐藏导航栏(如果需要) -->
<item name="android:windowFullscreen">true</item>
</style>
厂商特定适配(国内主流厂商)
华为刘海屏适配
// 检查是否支持刘海屏
public static boolean hasNotchInHuawei(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 (Exception e) {
e.printStackTrace();
}
return ret;
}
// 获取刘海尺寸
public static int[] getNotchSizeInHuawei(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 (Exception e) {
e.printStackTrace();
}
return ret;
}
小米刘海屏适配
// 小米刘海屏判断
public static boolean hasNotchInXiaomi(Context context) {
return context.getPackageManager()
.hasSystemFeature("ro.miui.notch");
}
// 获取小米刘海高度
public static int getNotchHeightInXiaomi(Context context) {
int resourceId = context.getResources()
.getIdentifier("notch_height", "dimen", "android");
if (resourceId > 0) {
return context.getResources().getDimensionPixelSize(resourceId);
}
return 0;
}
OPPO/VIVO 适配
// OPPO刘海屏判断
public static boolean hasNotchInOppo(Context context) {
return context.getPackageManager()
.hasSystemFeature("com.oppo.feature.screen.heteromorphism");
}
// VIVO刘海屏判断
public static boolean hasNotchInVivo(Context context) {
try {
ClassLoader cl = context.getClassLoader();
Class FtFeature = cl.loadClass("android.util.FtFeature");
Method method = FtFeature.getMethod("isFeatureSupport", int.class);
return (boolean) method.invoke(FtFeature, 0x00000020);
} catch (Exception e) {
return false;
}
}
最佳实践建议
- 使用官方API优先:优先使用Android P及以上版本的官方API
- 提供降级方案:为不支持全面屏的设备提供传统布局
- 测试多厂商设备:特别测试华为、小米、OPPO、VIVO等国内主流品牌
- 动态检测:运行时检测设备特性,动态调整布局
- 用户配置选项:提供是否启用全面屏模式的用户选项
完整适配工具类示例
object FullScreenUtils {
// 检查全面屏设备
fun isFullScreenDevice(context: Context): Boolean {
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> true
isNotchDevice(context) -> true
else -> false
}
}
// 获取安全区域
fun getSafeAreaInsets(activity: Activity): Rect {
val rect = Rect()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val displayCutout = activity.window.decorView
.rootWindowInsets?.displayCutout
if (displayCutout != null) {
rect.left = displayCutout.safeInsetLeft
rect.top = displayCutout.safeInsetTop
rect.right = displayCutout.safeInsetRight
rect.bottom = displayCutout.safeInsetBottom
}
}
return rect
}
// 应用全面屏适配
fun applyFullScreen(activity: Activity) {
activity.window.apply {
// 设置沉浸式
decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
)
// 设置刘海屏模式
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
// 设置状态栏透明
statusBarColor = Color.TRANSPARENT
}
}
}
通过以上方案,你可以为OpenClaw应用实现完善的全面屏适配,确保在不同厂商的全面屏设备上都能提供优秀的用户体验。

版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。