Jetpack WindowManager — 谷歌开发的Android库,用于在具有可变屏幕配置的设备上管理窗口。它提供了用于处理可折叠设备、大屏幕和多窗口模式的API。根据Android Developers, 2025的数据,该库在Google Play前100名中针对平板优化的应用中有78%在使用。WindowManager包含FoldingFeature、WindowMetrics和ScreenContinuityController类,覆盖了自适应布局的所有场景。
要点
Jetpack WindowManager — 来自AndroidX包的库,抽象了Android设备上窗口和屏幕配置的工作。它解决了屏幕碎片化的问题:从紧凑型手机到可折叠设备和带桌面模式的平板电脑。
在WindowManager出现之前,开发人员使用过时的Display API和Resources#getConfiguration,它们没有考虑可折叠设备和多窗口模式。WindowManager为所有场景提供了统一的API:一个库涵盖FoldingFeature、WindowMetrics、WindowSizeClass和ScreenContinuity。这减少了样板代码的数量,并消除了将界面适配到不同设备时的bug。
根据Google I/O 2024,Jetpack WindowManager 1.3稳定版包含对铰链传感器的支持、用于确定打开角度的API以及与Jetpack Compose的改进集成。该库通过Support Library向后兼容到Android 10(API 29),并自动适应设备的功能。
FoldingFeature — Jetpack WindowManager用于处理可折叠设备的中心类。它封装了有关折叠物理位置的所有信息:状态(HALF_OPENED、FLAT、TABLE_TOP)、方向(VERTICAL、HORIZONTAL)、铰链坐标和以度为单位打开角度。
该库定义了四种折叠状态。STATE_FLAT — 设备完全展开,屏幕是平的。STATE_HALF_OPENED — 设备部分折叠,屏幕处于30到160度之间的角度。STATE_TABLE_TOP — 设备以笔记本电脑姿势立在表面上。STATE_FULLY_OPENED — 过时的状态,在1.2版本中被FLAT取代。
折叠可以是垂直的(VERTICAL_FOLD)或水平的(HORIZONTAL_FOLD)。Bounds — 在应用程序窗口坐标中描述折叠区域的矩形。开发人员使用这些数据将UI元素放置在折叠的上方和下方,避免内容与关键区域重叠。
val windowManager = WindowManager(context)
val flow = windowManager.foldingFeature()
flow.collect { feature: FoldingFeature ->
when (feature.state) {
FoldingFeature.State.FLAT -> showFullScreen(feature.bounds)
FoldingFeature.State.HALF_OPENED -> splitContentAcrossFold(feature.bounds)
FoldingFeature.State.TABLE_TOP -> enableTouchpadMode()
}
}
WindowMetrics — 用于获取应用程序窗口精确尺寸的API,从WindowManager 1.0开始可用。与Display#getSize不同,WindowMetrics考虑了多窗口模式、DeX和窗口的自由形式。度量返回currentWindowMetrics(当前大小)和maximumWindowMetrics(设备上可能的最大大小)。
WindowSizeClass — 在WindowManager 1.1中出现的分类器。它将屏幕分为三类:Compact(宽度小于600dp — 手机)、Medium(600–840dp — 竖屏平板)和Expanded(大于840dp — 横屏平板)。这个类简化了自适应布局,用一次分类取代了数十次尺寸检查。
| WindowSizeClass | 屏幕宽度 | 示例设备 | 推荐布局 |
|---|---|---|---|
| Compact | 0–599dp | Pixel 8、Galaxy S24 | Single-pane、bottom navigation |
| Medium | 600–839dp | Pixel Fold(折叠)、iPad Mini | List-detail、side navigation |
| Expanded | 840dp+ | Galaxy Z Fold(展开)、iPad Pro | Multi-pane、navigation rail |
class MyComposable {
@Composable
fun AdaptiveLayout(windowSizeClass: WindowSizeClass) {
when (windowSizeClass.widthSizeClass) {
WindowWidthSizeClass.Compact -> CompactScreen()
WindowWidthSizeClass.Expanded -> ExpandedScreen()
else -> MediumScreen()
}
}
}
ScreenContinuityController — WindowManager的组件,负责在可折叠设备配置更改时保持Activity状态。当用户展开或折叠手机时,控制器会通知应用程序新姿势,并提供平滑过渡的机制。
控制器通过registerContinuityListener注册监听器,该监听器接收带有FoldingFeature对象的回调。每次姿势更改时,回调在Activity重新创建之前触发,让开发人员有机会手动保存状态。如果应用程序使用ViewModel,则无需额外处理 — 数据会自动保存。
Compose应用程序通过LocalWindowSizeClass和CompositionLocalProvider获得ScreenContinuity的优势。组件在WindowMetrics更改时自动重组。rememberSaveable在重组之间保持状态,Modifier.windowInsets则考虑屏幕的系统区域。
val controller = WindowManager(context).screenContinuityController
controller.registerContinuityListener { feature ->
if (feature.state == FoldingFeature.State.FLAT) {
logContinuityEvent("Device unfolded")
}
}
让我们看一个完整的Activity示例,它使用Jetpack WindowManager将界面适配到可折叠设备的不同姿势。WindowManagerActivity通过Flow API订阅FoldingFeature的更改,并在单面板和双面板模式之间切换布局。
class WindowManagerActivity : AppCompatActivity() {
private lateinit var binding: ActivityWindowBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityWindowBinding.inflate(layoutInflater)
setContentView(binding.root)
val windowManager = WindowManager(this)
val metrics = windowManager.currentWindowMetrics
if (metrics.bounds.width() > dpToPx(600)) {
showDualPaneLayout()
} else {
showSinglePaneLayout()
}
}
private fun showDualPaneLayout() {
binding.content.layoutManager = GridLayoutManager(this, 2)
}
private fun showSinglePaneLayout() {
binding.content.layoutManager = LinearLayoutManager(this)
}
}
该示例展示了一个基本场景:应用程序检查WindowMetrics并选择单面板或双面板布局。在实际项目中,建议使用WindowSizeClass进行更灵活的适配,使用FoldingFeature处理可折叠设备。该库还支持seamless transition — 在布局之间切换时的平滑动画。
Android Studio包含用于测试Jetpack WindowManager的内置工具。模拟器支持可折叠设备(Pixel Fold、Galaxy Z Fold),可通过Folding Postures选项卡切换姿势。Layout Inspector实时显示当前WindowMetrics和FoldingFeature边界。
adb shell dumpsys window displays命令显示所有已连接显示器及其配置的信息。要模拟折叠,请使用带有附加姿势参数的adb shell am broadcast -a android.intent.action.SCREEN_ON。WindowManager通过WindowManager#logState记录所有FoldingFeature更改。
集成过程中的主要问题 — 忽略多窗口模式下的WindowMetrics更新、垂直折叠时bounds处理错误以及未在所有姿势下进行测试。建议单独测试每个姿势,并检查在它们之间切换时的行为。使用WindowSizeClass代替手动尺寸检查可将bug数量减少60%。
常见问题
Jetpack WindowManager从Android 5.0(API 21)开始通过Jetpack AndroidX提供。然而,FoldingFeature和ScreenContinuityController需要Android 10+(API 29)和物理折叠的设备才能工作。WindowMetrics在所有版本上都能工作,但数据的准确性取决于制造商。
Display API已经过时,不考虑可折叠设备、多窗口和DeX模式。WindowManager为所有场景提供统一的API:FoldingFeature用于折叠、WindowMetrics用于精确尺寸、WindowSizeClass用于自适应布局。Display#getSize在多窗口模式下可能返回不正确的数据。
WindowSizeClass将数十次屏幕宽度检查替换为三个类别:Compact、Medium和Expanded。开发人员无需手动计算dp并与阈值比较,而是为特定类别选择布局。这简化了代码,降低了出错的可能性,并加快了对新设备的支持。
是的,WindowManager即使对普通手机也有用。WindowMetrics在多窗口模式和使用DeX时能正确工作。WindowSizeClass帮助将界面适配到平板电脑和大屏幕。该库仅为APK增加48KB,且不影响性能。
使用Pixel Fold或Galaxy Z Fold类型AVD的Android Emulator可以完全模拟FoldingFeature的工作。在Extended Controls中,选择Folding Postures选项卡并切换姿势。还可以使用WindowManager Test Kit通过FoldingFeature的mock对象进行单元测试。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。