适用于折叠设备的 Jetpack 窗口管理器
Jetpack 窗口管理器提供了可用于所有可折叠设备的标准 API。 它包含两个重要的类:
- DisplayFeature - 标识连续平面(如铰链或折叠)的中断。 窗口管理器将从布局更改回调返回显示功能的集合。
- FoldingFeature - 提供有关设备的特定特征的信息。 虽然 Surface Duo 只有一个折叠特征,但其他设备可能有多个。
类似的指南位于 Android Foldable Codelab 中。 有关详细信息,请参阅 Android 文档中的开发可折叠设备。也可在 GitHub 上找到 Android 团队示例。 Jetpack 发行说明记录了窗口管理器更新时的更改。
提示
Surface Duo 双屏库中的控件和帮助程序类可与窗口管理器结合使用。 按照说明将正确的包添加到应用项目中。
若要直接在代码中使用窗口管理器,请按照以下说明进行操作:
添加依赖项
确保顶级 build.gradle 文件中有
mavenCentral()
存储库:allprojects { repositories { google() mavenCentral() } }
请确保在模块级别的 build.gradle 文件中将
compileSdkVersion
和targetSdkVersion
设置为 API 31 或更新版本:android { compileSdkVersion 31 defaultConfig { targetSdkVersion 31 } ... }
在模块级别的 build.gradle 文件中添加以下依赖项:
- 视图
- Compose
dependencies { implementation "androidx.window:window:1.0.0" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0' }
在 Kotlin 代码中使用窗口管理器
访问 Kotlin 项目中的窗口管理器属性时,请务必设置正确的信息流。 否则,可能会收到过少或过多的事件更新,并且应用性能可能会受到影响。
若要初始化和使用 WindowInfoTracker
对象,请执行以下步骤:
在 MainActivity 类中,为
WindowInfoTracker
创建变量。 确保将import androidx.window.layout.WindowInfoTracker
添加到文件顶部。class MainActivity : AppCompatActivity() { private lateinit var windowInfoTracker: WindowInfoTracker
初始化活动的
onCreate
方法中的WindowInfoTracker
,设置流以从windowLayoutInfo
属性收集信息。- 视图
- Compose
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Initialize the window manager windowInfoTracker = WindowInfoTracker.getOrCreate(this@MainActivity) // Set up a flow lifecycleScope.launch(Dispatchers.Main) { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { windowInfoTracker.windowLayoutInfo(this@MainActivity) .collect { // Check FoldingFeature properties here } } } }
确保将这些导入项也添加到文件顶部:
import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch
添加代码以检查
WindowLayoutInfo
流中的折叠特征属性。 运行此代码时,活动将更新为当前设备状态并显示特征(如果跨折叠或铰链显示)。在下面的代码片段中,活动根据
FoldingFeature
属性显示不同的文本。- 视图
- Compose
此示例有一个称为
layout_change_text
的 TextView,显示封闭类型和任何检测到的折叠特征的isSeparating
值。override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) windowInfoTracker = WindowInfoTracker.getOrCreate(this@MainActivity) lifecycleScope.launch(Dispatchers.Main) { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { windowInfoTracker.windowLayoutInfo(this@MainActivity) .collect { newLayoutInfo -> layout_change_text.text = "No display features detected" for (displayFeature : DisplayFeature in newLayoutInfo.displayFeatures) { if (displayFeature is FoldingFeature && displayFeature.occlusionType == FoldingFeature.OcclusionType.NONE) { layout_change_text.text = "App is spanned across a fold, " + "isSeparating = ${displayFeature.isSeparating}" } if (displayFeature is FoldingFeature && displayFeature.occlusionType == FoldingFeature.OcclusionType.FULL) { layout_change_text.text = "App is spanned across a hinge, " + "isSeparating = ${displayFeature.isSeparating}" } } } } } }
折叠特征属性
WindowLayoutInfo
类具有一个 DisplayFeature
项的集合,其中的一个或多个项可以是 FoldingFeature 类的实例。
折叠特征具有以下属性:
bounds
- 折叠特征的边界矩形的坐标occlusionType
- 如果折叠特征隐藏内容(FULL
或NONE
)orientation
- 折叠特征的方向(HORIZONTAL
或VERTICAL
)state
- 折叠特征的角度(HALF_OPENED
或FLAT
)isSeparating
- 如果折叠特征将显示区域分隔为两个不同的部分
可以查询这些属性,以决定如何在配置更改后调整布局。
isSeparating
在决定放置控件的位置或要显示的内容窗格数时,请使用 isSeparating 属性。 此字段可确保应用在所有可折叠设备上提供最佳用户体验:
- 对于双屏设备,当应用跨铰链时,这始终为 true
- 对于其他可折叠设备,仅当状态是
HALF_OPENED
时(例如设备处于桌面状态时)这为 true
使用 isSeparating
属性决定是让应用的 UI 布局适应可折叠设备,还是在没有分隔时使用默认 UI:
private fun updateCurrentLayout(newLayoutInfo: WindowLayoutInfo) {
for (displayFeature in newLayoutInfo.displayFeatures) {
val foldFeature = displayFeature as? FoldingFeature
foldFeature?.let {
if (it.isSeparating) {
// The content is separated by the FoldingFeature.
// Here is where you should adapt your UI.
} else {
// The content is not separated.
// Users can see and interact with your UI properly.
}
}
}
}
若要查看有关如何使用此字段的更详细示例,请查看此 isSeparating 示例。
Google 还在其大屏幕和可折叠设备指南中提供了与此属性相关的文档和示例。
示例
surface-duo-jetpack-window-manager-samples GitHub 存储库包含大量 Kotlin 示例,它们演示使用 Jetpack 窗口管理器和传统视图系统生成的不同的双屏用户体验模式。
surface-duo-compose-samples GitHub 存储库还包含双屏 Kotlin 示例,该示例使用 Jetpack 窗口管理器,但在这些示例中,UI 是使用 Jetpack Compose 生成的。
Java API
请参阅 Jetpack 窗口管理器与 Java 博客文章和该 Java 示例,了解如何通过 WindowInfoTrackerCallbackAdapter
访问 WindowInfoTracker
类。