我来详细介绍一下OpenClaw(假设这是一个Android应用)的全面屏适配方案

openclaw AI使用帮助 1

基础配置

AndroidManifest.xml配置

<!-- 支持全面屏显示 -->
<meta-data
    android:name="android.max_aspect"
    android:value="2.4" />
<!-- 适配异形屏 -->
<meta-data
    android:name="android.notch_support"
    android:value="true" />

启用全屏模式

// 在Activity的onCreate中设置
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    WindowManager.LayoutParams params = getWindow().getAttributes();
    params.layoutInDisplayCutoutMode = 
        WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
    getWindow().setAttributes(params);
}

沉浸式状态栏适配

状态栏透明化

// 设置状态栏透明
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.setStatusBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
// 设置导航栏透明(可选)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    window.setNavigationBarColor(Color.TRANSPARENT);
}

内容延伸到状态栏

<!-- values-v21/styles.xml -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowTranslucentStatus">false</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

刘海屏/挖孔屏适配

获取安全区域

public class DisplayUtils {
    // 获取刘海屏安全区域
    public static Rect getSafeInsetRect(Window window) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            DisplayCutout cutout = window.getDecorView().getRootWindowInsets().getDisplayCutout();
            if (cutout != null) {
                return new Rect(
                    cutout.getSafeInsetLeft(),
                    cutout.getSafeInsetTop(),
                    cutout.getSafeInsetRight(),
                    cutout.getSafeInsetBottom()
                );
            }
        }
        return new Rect(0, 0, 0, 0);
    }
    // 获取状态栏高度
    public static int getStatusBarHeight(Context context) {
        int resourceId = context.getResources()
            .getIdentifier("status_bar_height", "dimen", "android");
        return resourceId > 0 ? 
            context.getResources().getDimensionPixelSize(resourceId) : 0;
    }
}

动态调整布局

public class FullScreenHelper {
    public static void adjustForFullScreen(View view) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            view.setOnApplyWindowInsetsListener((v, insets) -> {
                DisplayCutout cutout = insets.getDisplayCutout();
                if (cutout != null) {
                    int safeInsetTop = cutout.getSafeInsetTop();
                    int safeInsetBottom = cutout.getSafeInsetBottom();
                    // 设置padding避免内容被遮挡
                    v.setPadding(
                        v.getPaddingLeft(),
                        Math.max(v.getPaddingTop(), safeInsetTop),
                        v.getPaddingRight(),
                        Math.max(v.getPaddingBottom(), safeInsetBottom)
                    );
                }
                return insets;
            });
        }
    }
}

布局适配方案

ConstraintLayout适配方案

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">
    <!-- 状态栏占位View -->
    <View
        android:id="@+id/status_bar_placeholder"
        android:layout_width="0dp"
        android:layout_height="@dimen/status_bar_height"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
    <!-- 主要内容区域 -->
    <androidx.core.widget.NestedScrollView
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/status_bar_placeholder"
        app:layout_constraintBottom_toTopOf="@id/nav_bar_placeholder"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">
        <!-- 内容 -->
    </androidx.core.widget.NestedScrollView>
    <!-- 导航栏占位View -->
    <View
        android:id="@+id/nav_bar_placeholder"
        android:layout_width="0dp"
        android:layout_height="@dimen/nav_bar_height"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

边距适配方案

<!-- values/dimens.xml -->
<dimen name="status_bar_height">24dp</dimen>
<dimen name="nav_bar_height">48dp</dimen>
<!-- values-v21/dimens.xml -->
<dimen name="status_bar_height">@android:dimen/status_bar_height</dimen>
<!-- values-xxhdpi/dimens.xml (针对高屏占比设备) -->
<dimen name="status_bar_height">28dp</dimen>

厂商特定适配

华为刘海屏适配

public class HuaweiNotchUtils {
    public static boolean hasNotch(Context context) {
        try {
            ClassLoader cl = context.getClassLoader();
            Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
            return (boolean) get.invoke(HwNotchSizeUtil);
        } catch (Exception e) {
            return false;
        }
    }
    public static void setFullScreenWindow(Activity activity) {
        try {
            WindowManager.LayoutParams layoutParams = activity.getWindow().getAttributes();
            Class layoutParamsExCls = Class.forName("com.huawei.android.view.LayoutParamsEx");
            Constructor con = layoutParamsExCls.getConstructor(WindowManager.LayoutParams.class);
            Object layoutParamsExObj = con.newInstance(layoutParams);
            Method method = layoutParamsExCls.getMethod("addHwFlags", int.class);
            method.invoke(layoutParamsExObj, 0x00010000); // FLAG_NOTCH_SUPPORT
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

小米刘海屏适配

public class XiaomiNotchUtils {
    public static boolean hasNotch(Context context) {
        try {
            return "1".equals(SystemProperties.get("ro.miui.notch"));
        } catch (Exception e) {
            return false;
        }
    }
    public static int getNotchHeight(Context context) {
        int resourceId = context.getResources()
            .getIdentifier("notch_height", "dimen", "android");
        return resourceId > 0 ? 
            context.getResources().getDimensionPixelSize(resourceId) : 0;
    }
}

手势导航适配

全屏手势处理

public class GestureNavigationHelper {
    public static void handleGestureNavigation(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // 启用全屏手势
            activity.getWindow().getAttributes().systemUiVisibility |= 
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
            // 监听导航栏显示/隐藏
            View decorView = activity.getWindow().getDecorView();
            decorView.setOnSystemUiVisibilityChangeListener(visibility -> {
                boolean isNavigationHidden = (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
                adjustBottomPadding(activity, isNavigationHidden);
            });
        }
    }
    private static void adjustBottomPadding(Activity activity, boolean navigationHidden) {
        View rootView = activity.findViewById(android.R.id.content);
        if (rootView != null) {
            int bottomPadding = navigationHidden ? 0 : getNavigationBarHeight(activity);
            rootView.setPadding(
                rootView.getPaddingLeft(),
                rootView.getPaddingTop(),
                rootView.getPaddingRight(),
                bottomPadding
            );
        }
    }
}

测试建议

测试设备覆盖

  • 带刘海的设备(iPhone X样式)
  • 挖孔屏设备
  • 弹出式摄像头设备
  • 屏下摄像头设备
  • 曲面屏设备

测试场景

// 编写测试用例
@Test
public void testFullScreenLayout() {
    // 测试横竖屏切换
    // 测试手势导航
    // 测试异形屏区域点击
    // 测试安全区域显示
}

总结建议

  1. 优先使用Android官方API(API Level 28+)
  2. 渐进增强:为旧版本提供fallback方案
  3. 动态适配:运行时检测设备特性
  4. 用户可选:提供设置选项让用户选择显示模式
  5. 充分测试:覆盖主流厂商的不同全面屏方案

这样的适配方案能够确保OpenClaw在各种全面屏设备上都有良好的显示效果和用户体验。

我来详细介绍一下OpenClaw(假设这是一个Android应用)的全面屏适配方案-第1张图片-AI小龙虾下载官网 - openclaw下载 - openclaw小龙虾

标签: OpenClaw 全面屏适配

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