各位父老乡亲们,今天咱们来唠唠折叠屏适配这个让人又爱又恨的话题。自从某米某为开始玩"手机劈叉"之后,我们程序员的发际线又集体后移了3厘米。每次看到设计师拿着折叠屏手机摆出"看,这是朕为你打下的江山"的表情,我都想掏出祖传的Android Studio教他做人...
一、折叠屏的七十二变
先来认识一下我们的对手:
-
展开态:宛如平板电脑的霸道总裁
-
折叠态:假装自己是普通手机的戏精
-
帐篷模式:别问,问就是在模仿埃菲尔铁塔
-
书本模式:建议配合《Android开发艺术探索》食用更佳
二、适配三字经:查、变、动
1. 查设备状态(使用Jetpack WindowManager)
// 第一步:导包(重要程度堪比出门带手机)
implementation "androidx.window:window:1.0.0"
class MainActivity : ComponentActivity() {
private lateinit var windowInfoRepo: WindowInfoRepository
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 第二步:注册设备状态监听
windowInfoRepo = WindowInfoRepository.getOrCreate(this)
lifecycleScope.launch(Dispatchers.Main) {
windowInfoRepo.windowLayoutInfo.collect { layoutInfo ->
layoutInfo.displayFeatures.forEach { feature ->
if (feature is FoldingFeature) {
// 第三步:获取折叠状态
when {
feature.state == FoldingFeature.State.FLAT ->
println("手机进入贤者模式(完全展开)")
feature.orientation == FoldingFeature.Orientation.HORIZONTAL ->
println("手机正在表演一字马")
feature.isSeparating ->
println("检测到物理分界线,准备跑路")
}
}
}
}
}
}
}
2. 布局变形记
在res目录下新建资源文件夹:
res/
└── layout/
├── main_activity.xml // 默认布局
└── layout-w600dp/ // 展开态布局(600dp是折叠屏常见阈值)
└── main_activity.xml
使用ConstraintLayout的宝藏特性:
<androidx.constraintlayout.widget.ConstraintLayout
tools:showPaths="true">
<ImageView
android:id="@+id/hero_image"
app:layout_constraintWidth_percent="0.6"
app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintGuide_percent="0.3" />
<!-- 使用Barrier防止内容被铰链吃掉 -->
<androidx.constraintlayout.widget.Barrier
android:id="@+id/hinge_barrier"
app:barrierDirection="end"
app:constraint_referenced_ids="hero_image"/>
</androidx.constraintlayout.widget.ConstraintLayout>
3. 动态布局调整(像极了你女票的脾气)
// 实时监听屏幕变化
val configCallback = object : ComponentActivity.ConfigurationChanged() {
override fun onConfigurationChanged(newConfig: Configuration) {
when (newConfig.smallestScreenWidthDp) {
in 600..800 -> showTabletUI()
else -> showPhoneUI()
}
// 处理被折叠屏切断的区域
window.decorView.viewTreeObserver.addOnDrawListener {
handleOverlapWithHinge()
}
}
}
// 处理铰链遮挡(就像处理婆媳关系)
private fun handleOverlapWithHinge() {
val windowRect = windowManager.currentWindowMetrics.bounds
val foldFeature = getFoldingFeature() // 获取折叠区域
foldFeature?.let {
if (it.isSeparating) {
val foldPosition = it.bounds
// 把重要内容移出危险区域
binding.btnCheckout.apply {
if (x < foldPosition.left) {
translationX = foldPosition.left.toFloat() + 32.dp
}
}
}
}
}
三、避坑指南(血泪总结)
-
多窗口模式:你的Activity可能正在和别人的Activity谈恋爱(共享屏幕)
-
生命周期陷阱:折叠/展开时不是走onDestroy哦,而是onConfigurationChanged
-
测试地狱:建议购买各大品牌折叠屏,或者使用官方模拟器(老板:你看我像不像ATM?)
-
防手抖设计:用户可能在折叠过程中疯狂点击,需要添加交互屏蔽
四、终极奥义
记住三句箴言:
-
布局弹性化:像你的钱包一样能屈能伸
-
状态随时查:比查男朋友手机还频繁
-
设计分场景:展开时是杜拉拉,折叠时是林黛玉
最后送大家一道护身符(在manifest中声明支持):
<application
android:resizeableActivity="true">
<activity
android:name=".MainActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout" />
</application>
最后的最后,当你终于适配完所有折叠屏机型时,手机厂商发布了三折屏...(程序员卒)