iOS 刘海屏适配
Safe Area 安全区域
// iOS 中获取安全区域
if #available(iOS 11.0, *) {
let safeArea = UIApplication.shared.windows.first?.safeAreaInsets
let topPadding = safeArea?.top ?? 0
let bottomPadding = safeArea?.bottom ?? 0
}
// 在布局中使用安全区域
let safeAreaLayoutGuide = view.safeAreaLayoutGuide
Info.plist 配置
<!-- 适配 iPhone X 及之后机型 --> <key>UIStatusBarStyle</key> <string>UIStatusBarStyleDarkContent</string> <key>UIViewControllerBasedStatusBarAppearance</key> <true/>
Android 刘海屏适配
适配模式设置
<!-- AndroidManifest.xml -->
<application
android:theme="@style/AppTheme">
<meta-data
android:name="android.max_aspect"
android:value="2.4" />
</application>
<!-- 允许全屏显示 -->
<activity
android:name=".MainActivity"
android:theme="@style/FullScreenTheme">
</activity>
布局适配
// 获取刘海屏信息
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val windowInsets = window.decorView.rootWindowInsets
val displayCutout = windowInsets?.displayCutout
val safeInsetLeft = displayCutout?.safeInsetLeft ?: 0
val safeInsetTop = displayCutout?.safeInsetTop ?: 0
val safeInsetRight = displayCutout?.safeInsetRight ?: 0
val safeInsetBottom = displayCutout?.safeInsetBottom ?: 0
}
// 设置全屏模式
window.decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
)
XML 布局适配
<!-- 使用系统导航栏高度 -->
<View
android:id="@+id/statusBarPlaceholder"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
<!-- 使用 ConstraintLayout 约束到系统栏 -->
<androidx.constraintlayout.widget.ConstraintLayout>
<View
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Flutter 跨平台适配
SafeArea 组件
Widget build(BuildContext context) {
return SafeArea(
top: true,
bottom: true,
left: true,
right: true,
child: YourWidget(),
);
}
获取刘海屏信息
import 'dart:ui'; // 获取状态栏高度 final double statusBarHeight = MediaQueryData.fromWindow(window).padding.top; final double bottomBarHeight = MediaQueryData.fromWindow(window).padding.bottom;
响应式布局
class NotchAdaptiveWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final padding = MediaQuery.of(context).padding;
return Container(
padding: EdgeInsets.only(
top: padding.top,
bottom: padding.bottom,
),
child: YourContentWidget(),
);
}
}
CSS Web 适配
viewport-fit 属性
<meta name="viewport" content=" width=device-width, initial-scale=1.0, viewport-fit=cover ">
CSS 安全区域变量
/* iPhone X 及之后机型的安全区域 */
.safe-area {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
/* 适配深色模式 */
@media (prefers-color-scheme: dark) {
.notch-area {
background-color: #000;
}
}
JavaScript 检测
// 检测是否为刘海屏设备
const isNotchedDevice = () => {
const aspectRatio = window.screen.width / window.screen.height;
return aspectRatio > 2;
};
// 获取安全区域
const safeAreaInsets = {
top: parseInt(getComputedStyle(document.documentElement)
.getPropertyValue('--safe-area-inset-top')) || 0,
bottom: parseInt(getComputedStyle(document.documentElement)
.getPropertyValue('--safe-area-inset-bottom')) || 0,
};
Unity 游戏引擎适配
获取安全区域
using UnityEngine;
public class NotchAdapter : MonoBehaviour
{
void Start()
{
// iOS 安全区域
#if UNITY_IOS
var safeArea = Screen.safeArea;
var anchorMin = safeArea.position;
var anchorMax = anchorMin + safeArea.size;
anchorMin.x /= Screen.width;
anchorMin.y /= Screen.height;
anchorMax.x /= Screen.width;
anchorMax.y /= Screen.height;
GetComponent<RectTransform>().anchorMin = anchorMin;
GetComponent<RectTransform>().anchorMax = anchorMax;
#endif
// Android 裁切区域
#if UNITY_ANDROID
if (Application.platform == RuntimePlatform.Android)
{
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
using (AndroidJavaObject window = currentActivity.Call<AndroidJavaObject>("getWindow"))
{
var decorView = window.Call<AndroidJavaObject>("getDecorView");
var insets = decorView.Call<AndroidJavaObject>("getRootWindowInsets");
// 处理 insets
}
}
#endif
}
}
最佳实践建议
设计原则避开关键区域**:避免在状态栏、导航栏区域放置交互元素
- 灵活布局:使用相对布局而非绝对定位
- 测试全面:在各种刘海屏设备上测试
测试清单
☐ iPhone X/XS/11/12/13/14/15 系列
☐ Android 各种刘海屏、挖孔屏设备
☐ 横屏和竖屏模式
☐ 深色/浅色模式
☐ 旋转适配
工具推荐
- iOS: Xcode 的 Simulator
- Android: Android Studio 的 Layout Inspector
- 在线测试: BrowserStack, Sauce Labs
这些方案可以根据 OpenClaw 的具体技术栈选择使用,核心思想是尊重系统提供的安全区域,确保内容不会被刘海或状态栏遮挡,同时保持用户体验的一致性。

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