iOS适配方案
安全区域适配
// 使用安全区域布局
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 11.0, *) {
// 适配刘海屏
let safeArea = view.safeAreaLayoutGuide
openClawView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
openClawView.topAnchor.constraint(equalTo: safeArea.topAnchor, constant: 20),
openClawView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor),
openClawView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor),
openClawView.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor)
])
}
}
状态栏高度获取
// 获取刘海屏状态栏高度
func getStatusBarHeight() -> CGFloat {
if #available(iOS 13.0, *) {
let window = UIApplication.shared.windows.first
return window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
} else {
return UIApplication.shared.statusBarFrame.height
}
}
Android适配方案
沉浸式状态栏
// 设置沉浸式状态栏
fun setImmersiveMode(activity: Activity) {
// Android 4.4+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}
// Android 5.0+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
activity.window.statusBarColor = Color.TRANSPARENT
}
// Android 6.0+ 设置全屏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
activity.window.decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
}
}
获取刘海屏信息
// 检查是否为刘海屏
fun isNotchScreen(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val displayCutout = context.getSystemService<WindowManager>()
?.defaultDisplay?.cutout
displayCutout != null
} else {
false
}
}
// 获取刘海高度
fun getNotchHeight(context: Context): Int {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val displayCutout = context.getSystemService<WindowManager>()
?.defaultDisplay?.cutout
displayCutout?.safeInsetTop ?: 0
} else {
0
}
}
Flutter适配方案
import 'package:flutter/services.dart';
class NotchAdapter {
// 获取状态栏高度
static double getStatusBarHeight(BuildContext context) {
return MediaQuery.of(context).padding.top;
}
// 获取底部安全区域高度
static double getBottomSafeHeight(BuildContext context) {
return MediaQuery.of(context).padding.bottom;
}
// 设置沉浸式状态栏
static void setImmersiveStatusBar() {
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.light,
));
}
}
// 使用示例
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
top: false, // 禁用顶部安全区域,手动处理
child: Container(
padding: EdgeInsets.only(
top: NotchAdapter.getStatusBarHeight(context) + 20,
bottom: NotchAdapter.getBottomSafeHeight(context),
),
child: YourOpenClawContent(),
),
),
);
}
Web适配方案
/* CSS环境变量适配 */
:root {
--safe-area-inset-top: env(safe-area-inset-top);
--safe-area-inset-bottom: env(safe-area-inset-bottom);
--safe-area-inset-left: env(safe-area-inset-left);
--safe-area-inset-right: env(safe-area-inset-right);
}
.openclaw-container {
/* 基础样式 */
padding-top: 20px;
/* 刘海屏适配 */
padding-top: calc(20px + var(--safe-area-inset-top, 0px));
padding-bottom: calc(20px + var(--safe-area-inset-bottom, 0px));
padding-left: calc(20px + var(--safe-area-inset-left, 0px));
padding-right: calc(20px + var(--safe-area-inset-right, 0px));
/* 或者使用viewport-fit */
min-height: 100vh;
min-height: -webkit-fill-available;
}
/* 在meta标签中设置 */
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
游戏引擎适配
Unity适配
// Unity中获取安全区域
using UnityEngine;
public class NotchAdapter : MonoBehaviour
{
void Start()
{
// iOS适配
#if UNITY_IOS
ApplySafeArea_iOS();
#endif
// Android适配
#if UNITY_ANDROID
ApplySafeArea_Android();
#endif
}
void ApplySafeArea_iOS()
{
var safeArea = Screen.safeArea;
var canvas = GetComponent<Canvas>();
var rectTransform = canvas.GetComponent<RectTransform>();
// 将安全区域转换为Canvas空间
var anchorMin = safeArea.position;
var anchorMax = safeArea.position + safeArea.size;
anchorMin.x /= Screen.width;
anchorMin.y /= Screen.height;
anchorMax.x /= Screen.width;
anchorMax.y /= Screen.height;
rectTransform.anchorMin = anchorMin;
rectTransform.anchorMax = anchorMax;
}
}
测试建议
-
设备覆盖测试

- iPhone X/XS/11/12/13/14/15系列
- 华为P系列、Mate系列
- 小米8/9/10/11/12系列
- OPPO/Vivo刘海屏机型
-
功能测试点
- 状态栏是否遮挡内容
- 手势操作区域是否正常
- 横竖屏切换适配
- 旋转动画流畅性
-
兼容性考虑
- 非刘海屏设备正常显示
- 不同系统版本兼容
- 动态刘海(可隐藏)适配
最佳实践
- 优先使用系统提供的安全区域API
- 避免硬编码尺寸值
- 在设计和开发初期就考虑刘海屏适配
- 提供适配开关,方便调试
- 考虑未来可能出现的挖孔屏、折叠屏等新形态
这样的适配方案能确保OpenClaw在各种刘海屏设备上都有良好的用户体验。
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。