一、理解折叠屏设备特性
-
屏幕状态:
- 折叠(Closed / Half-open) :小屏(Cover Screen)
- 展开(Opened) :大屏(Main Screen)
-
屏幕尺寸与比例差异大:
- 折叠后通常为普通手机尺寸(如 6 英寸)
- 展开后可能接近平板(如 8 英寸以上),且长宽比可能非常规(如 6:5、4:3)
-
铰链区域(Hinge) :
- 某些设备(如 Surface Duo)存在物理缝隙或非连续显示区域
- 可通过
displayCutout或WindowInsets获取相关信息
##二、适配策略
1. 响应式布局(Responsive Layout)
使用 ConstraintLayout、Fragments、Jetpack Compose 等支持动态布局的技术。
- 使用
res/layout-sw600dp/等资源限定符区分小屏/大屏布局 - 避免硬编码尺寸,使用
wrap_content、match_parent、weight、Guideline等
<!-- res/layout/activity_main.xml --> <!-- 手机 -->
<!-- res/layout-sw600dp/activity_main.xml --> <!-- 平板/展开态 -->
2. 监听屏幕折叠状态变化
从 Android 10(API 29)起,可通过 Configuration Changes 监听折叠状态:
方法一:监听 configChanges
在 AndroidManifest.xml 中声明:
<activity
android:name=".MainActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout"
android:exported="true">
</activity>
在 Activity 中重写:
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// 检查当前是否为大屏
if (newConfig.smallestScreenWidthDp >= 600) {
// 大屏布局逻辑
} else {
// 小屏布局逻辑
}
}
对于一些自定义view,可以在onViewAttachToWindow中重新计算尺寸。
方法二:使用 Jetpack WindowManager(推荐)
Google 推荐使用 Jetpack WindowManager 库来处理折叠设备。
添加依赖:
implementation "androidx.window:window:1.3.0"
监听折叠状态:
val windowInfoRepo = WindowInfoTracker.getOrCreate(this)
lifecycleScope.launch(Dispatchers.Main) {
windowInfoRepo.windowLayoutInfo(this@MainActivity)
.collect { layoutInfo ->
val foldFeatures = layoutInfo.displayFeatures.filterIsInstance<FoldingFeature>()
if (foldFeatures.isNotEmpty()) {
val state = foldFeatures[0].state // STATE_FLAT (展开) / STATE_HALF_OPENED (半开)
val isFolded = state == FoldingFeature.State.HALF_OPENED
// 根据状态调整 UI
}
}
}
3. 多窗口与连续性体验
- 不要阻止多窗口模式:避免设置
resizeableActivity="false" - 保存状态:确保在屏幕切换时 UI 状态不丢失(使用 ViewModel + SavedStateHandle)
- 任务连续性:用户从折叠切换到展开时,应保持当前操作上下文(如正在编辑的表单、播放的视频等)
4. 测试
- 使用 Android Studio 自带的 Device Manager 创建折叠屏模拟器(如 “Galaxy Fold”)
- 在真实设备上测试(如 Pixel Fold、三星 Fold 系列)
- 使用
adb命令模拟折叠状态(需配合 WindowManager 支持):
# 模拟折叠
adb shell wm set-folding-feature-state 0 STATE_HALF_OPENED
# 模拟展开
adb shell wm set-folding-feature-state 0 STATE_FLAT
注意:该命令仅在支持 WindowManager 的设备/模拟器上有效。
三、进阶优化
- 分屏双窗交互:在大屏上可采用主-详(Master-Detail)布局
- 拖拽与跨区域交互:利用大屏空间实现更丰富的手势操作
- 避免 UI 被铰链遮挡:通过
FoldingFeature.bounds获取铰链区域,避开关键控件
val hingeBounds = foldFeature.bounds
// 调整布局 margin 或使用 Guideline 避开该区域