前言
坚守安卓原生开发很久很久了,flutter 还是没有学会,所以目前依旧使用 Compose,资料不是很多,靠着官方文档和部分ai能力整理总结一下。
介绍
下面介绍一下屏幕感知会用到的类及其释义。
WindowSizeClass 窗口尺寸类别,用于标识窗口尺寸
完整包名:androidx.window.core.layout.WindowSizeClass,旗下有两个类:WindowWidthSizeClass 和 WindowHeightSizeClass,分别对应宽度尺寸类别和高度尺寸类别,这两个类别会在屏幕旋转的时候变动,无需判断屏幕方向,只关心尺寸级别。
它们都有三种不同的尺寸级别枚举:
COMPACT:小尺寸MEDIUM:中等尺寸EXPANDED:大尺寸
尺寸详情请参考:官方文档
Posture 设备姿态
-
isTabletop:为true时,标识设备为笔记本电脑模式,像笔记本电脑一样放置,可根据这个状态针对性的绘制 ui 排版。 -
hingList:铰链信息列表,这里的铰链可能有多个,可以理解为:每一个可折叠部位,都视作一个铰链,举例:双折叠有一个铰链,三折叠有两个铰链。
HingeInfo 铰链
铰链是折叠屏感知中最核心的部分,可以根据不同形态的折叠屏进行精确的控制,字段如下:
bounds:铰链在屏幕当中的区域矩形,绘制 ui 时要,避开这些区域,通常情况下无遮挡铰链只有宽度或高度。isOccluding:铰链区域是否会遮挡屏幕,如果遮挡,就需要搭配bounds字段调整 ui 绘制。isFlat:屏幕完全展开时为trueisSeparating:屏幕部分展开时为trueisVertical:铰链是否为垂直放线,为true时,铰链是垂直方向,屏幕可以左右开合,为false时,铰链是水平方向,屏幕可以上下开合。
准备
首先,导入 Jetpack Compose BOM,下面以 toml 文件为例,版本 2025.12.00
ini
[versions]
compose-bom = "2025.12.00"
[libraries]
# 主包必须要依赖
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
# 窗口感知和适配需要依赖的包
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-compose-material3-window-size = { group = "androidx.compose.material3", name = "material3-window-size-class" }
androidx-compose-material3-adaptive = { group = "androidx.compose.material3.adaptive", name = "adaptive" }
androidx-compose-material3-adaptive-layout = { group = "androidx.compose.material3.adaptive", name = "adaptive-layout" }
# 其他Compose包根据自己项目需要依赖,略
然后将声明好的包导入进项目 gradle 文件(Module 级别,以 kts 文件为例)
scss
dependencies{
//其他依赖,略
//导入窗口感知依赖,如果跨包导入,使用api方法替换implementation方法
implementation(platform(libs.androidx.compose.bom))
androidTestImplementation(platform(libs.androidx.compose.bom))
api(libs.androidx.compose.material3)
api(libs.androidx.compose.material3.window.size)
api(libs.androidx.compose.material3.adaptive)
api(libs.androidx.compose.material3.adaptive.layout)
}
核心逻辑
kotlin
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.runtime.Composable
import androidx.window.core.layout.WindowWidthSizeClass
@Compose
fun TestScreen(){
//读取窗口信息
val info = currentWindowAdaptiveInfo()
//获取窗口尺寸类型
val size = info.windowSizeClass
//宽度尺寸判断
when(size.windowWidthSizeClass){
WindowWidthSizeClass.COMPATC -> {
//todo 宽度,小
}
WindowWidthSizeClass.MEDIUM -> {
//todo 宽度,中
}
WindowWidthSizeClass.EXPANDED -> {
//todo 宽度,大
}
}
//高度尺寸判断
when(size.windowHeightSizeClass){
WindowHeightSizeClass.COMPACT -> {
//todo 高度,小
}
WindowHeightSizeClass.MEDIUM -> {
//todo 高度,中
}
WindowHeightSizeClass.EXPANDED -> {
//todo 高度,大
}
}
//获取窗口姿态情况
val posture = info.windowPosture
//笔记本电脑姿态
posture.isTabletop
//获取铰链详情(只有折叠屏被打开时才有信息,否则hingeList为空)
posture.hingeList.forEach { hinge ->
//铰链在窗口中的区域(矩形)
hinge.bounds
//铰链区域是否会遮挡窗口
hinge.isOccluding
//完全展开(平摊状态)
hinge.isFlat
//部分展开(铰链打开、分离)
hinge.isSeparating
//铰链方向,true垂直,左右折叠;false水平,上下折叠
hinge.isVertical
}
}
要让每个界面都精确适配起来确实是个大工程,需要利用这些基础信息来做。
未解决的问题(可能)
去除 letterBox 窗口之后,即不限制屏幕旋转方向,会造成一定的适配问题,比如将一个竖屏的手机横放,此时宽度非常宽,但高度就很矮,像是登录界面就需要考虑换一种呈现方式,上下滑动的登录页面体验感大打折扣。我已经试过了在折叠屏关闭时,锁定屏幕方向,打开时解锁,但是会有生命周期的问题造成崩溃,因为旋转屏幕和展开屏幕都会重走生命周期,即使是配置 configChanges 也没有效果,不知道是什么原因。如果有解决方案,欢迎指正。
结尾
技术不高,水平有限,如有错误或不足,欢迎批评。