Android 全面屏适配
刘海屏/挖孔屏适配
<!-- AndroidManifest.xml 中配置 -->
<application
android:theme="@style/AppTheme">
<!-- 适配刘海屏 -->
<meta-data
android:name="android.max_aspect"
android:value="2.4" />
</application>
<!-- 针对具体Activity -->
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize"
android:screenOrientation="portrait">
<!-- 允许延伸到刘海区域 -->
<meta-data
android:name="android.notch_support"
android:value="true" />
</activity>
代码中动态适配
// 检测是否有刘海屏
fun hasNotch(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val displayCutout = window.decorView.rootWindowInsets?.displayCutout
displayCutout != null
} else {
// 厂商特定方法
when {
isXiaomi() -> checkXiaomiNotch()
isHuawei() -> checkHuaweiNotch()
isOppo() -> checkOppoNotch()
isVivo() -> checkVivoNotch()
else -> false
}
}
}
// 设置刘海屏模式
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val params = window.attributes
params.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
window.attributes = params
}
沉浸式状态栏
// 沉浸式状态栏适配
fun setImmerseStatusBar(activity: Activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val window = activity.window
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.statusBarColor = Color.TRANSPARENT
var systemUiVisibility = window.decorView.systemUiVisibility
systemUiVisibility = systemUiVisibility or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
window.decorView.systemUiVisibility = systemUiVisibility
}
}
iOS 全面屏适配
Safe Area 适配
// 使用 Safe Area Layout Guide
override func viewDidLoad() {
super.viewDidLoad()
// 创建约束时使用 safeAreaLayoutGuide
NSLayoutConstraint.activate([
headerView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
footerView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
])
// 适配 iPhone 底部 Home Indicator
if #available(iOS 11.0, *) {
additionalSafeAreaInsets = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)
}
}
// 获取安全区域
func getSafeAreaInsets() -> UIEdgeInsets {
if #available(iOS 11.0, *) {
return view.safeAreaInsets
}
return UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
}
刘海屏特定处理
// 检测设备类型
func isiPhoneXSeries() -> Bool {
guard let keyWindow = UIApplication.shared.keyWindow else {
return false
}
if #available(iOS 11.0, *) {
return keyWindow.safeAreaInsets.bottom > 0
}
return false
}
// 适配状态栏高度
func statusBarHeight() -> 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
}
}
跨平台适配方案
React Native 适配
// 使用 SafeAreaView
import { SafeAreaView, StatusBar, Platform } from 'react-native';
const App = () => {
return (
<SafeAreaView style={styles.container}>
<StatusBar
barStyle="dark-content"
backgroundColor="transparent"
translucent={true}
/>
{/* 内容 */}
</SafeAreaView>
);
};
// 获取安全区域
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const MyComponent = () => {
const insets = useSafeAreaInsets();
return (
<View style={{
paddingTop: insets.top,
paddingBottom: insets.bottom,
}}>
{/* 内容 */}
</View>
);
};
Flutter 适配
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
class FullScreenPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 设置沉浸式状态栏
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
));
return Scaffold(
body: SafeArea(
child: Container(
// 内容
),
),
);
}
}
// 获取安全区域
final padding = MediaQuery.of(context).padding;
final safeAreaHeight = MediaQuery.of(context).size.height - padding.top - padding.bottom;
设计规范适配
边距和间距
普通屏幕:左右边距 16-20dp
全面屏:左右边距 24-32dp
底部安全区域:至少 34dp(iOS)、48dp(Android手势区)
手势冲突处理
// Android 手势冲突处理
class GestureConflictActivity : AppCompatActivity() {
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
// 处理边缘手势冲突
if (ev.action == MotionEvent.ACTION_DOWN) {
if (isInGestureArea(ev.x, ev.y)) {
// 特殊处理手势区域
return handleGestureAreaTouch(ev)
}
}
return super.dispatchTouchEvent(ev)
}
private fun isInGestureArea(x: Float, y: Float): Boolean {
val screenHeight = resources.displayMetrics.heightPixels
return y > screenHeight - convertDpToPixel(48f)
}
}
测试要点
-
设备覆盖测试:

- iPhone X/XS/11/12/13/14/15 系列
- 各种 Android 刘海屏、挖孔屏设备
- 折叠屏设备
-
场景测试:
- 横竖屏切换
- 键盘弹出
- 全屏视频播放
- 页面跳转过渡
-
功能验证:
- 状态栏颜色和内容对比度
- 底部操作区域可点击性
- 手势操作无冲突
最佳实践
- 使用系统提供的 Safe Area API
- 避免在安全区域内放置重要交互元素
- 适配各种屏幕比例和分辨率
- 提供横屏模式支持
- 定期更新设备适配列表
通过以上方案,OpenClaw 可以在各种全面屏设备上获得良好的用户体验。
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。