我来详细介绍一下OpenClaw(开源爪哇)的全面屏适配方案。全面屏适配主要涉及沉浸式状态栏、异形屏(刘海屏、挖孔屏)处理以及手势导航适配

openclaw 中文openclaw 1

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;
    }
}

最佳实践建议

  1. 使用官方API优先:优先使用Android P及以上版本的官方API
  2. 提供降级方案:为不支持全面屏的设备提供传统布局
  3. 测试多厂商设备:特别测试华为、小米、OPPO、VIVO等国内主流品牌
  4. 动态检测:运行时检测设备特性,动态调整布局
  5. 用户配置选项:提供是否启用全面屏模式的用户选项

完整适配工具类示例

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应用实现完善的全面屏适配,确保在不同厂商的全面屏设备上都能提供优秀的用户体验。

我来详细介绍一下OpenClaw(开源爪哇)的全面屏适配方案。全面屏适配主要涉及沉浸式状态栏、异形屏(刘海屏、挖孔屏)处理以及手势导航适配-第1张图片-OpenClaw下载中文-AI中文智能体

标签: 全面屏适 配OpenClaw

抱歉,评论功能暂时关闭!