可折叠设备布局
重要
本文介绍的功能和指南为公共预览版,在正式发布之前可能会有重大修改。 Microsoft 不对此处提供的信息作任何明示或默示的担保。
重要
只有在将活动根视图附加到窗口后,才可看到此视图的内容。 之所以是这种情况是因为实现基于窗口管理器库,并且窗口管理器仅在视图附加到窗口后才会正常工作。
FoldableLayout
组件是一种自定义布局,当应用程序在可折叠设备上运行时,该组件可以不同方式定位其子元素。 该组件可以将屏幕拆分为两个区域,具体取决于折叠功能的位置和方向。 拆分屏幕后,可以并排保留两个子容器,也可以将一个子容器置于另一个容器之上。
单屏布局 | 双屏布局 |
---|---|
XML 属性
single_screen_layout_id
- 接收要在单屏模式下显示的布局 ID。dual_screen_start_layout_id
- 接收要在双屏模式的启动容器中显示的布局 ID。dual_screen_end_layout_id
- 接收要在双屏模式的启动容器中显示的布局 ID。
当应用程序在可折叠设备上运行时,FoldableLayout
还可以创建单个容器。
我们添加了四个新属性,可帮助你创建所需的 UI:
dual_portrait_single_layout_id
- 接收双纵向单容器的布局 ID。is_dual_portrait_single_container
- 创建空的双纵向单容器。dual_landscape_single_layout_id
- 接收双横向单容器的布局 ID。is_dual_landscape_single_container
- 创建空的双横向单容器。
smallestScreenSize 支持
当某项活动过渡到新的屏幕模式但未重新创建它(因为在清单文件中设置了标志 smallestScreenSize
)时,布局将检测新配置并自动调整容器的大小,甚至根据 FoldableLayout 配置添加或删除第二个容器。
Android Studio 预览版
tools_hinge_color
- 在布局预览中选择铰链颜色。tools_screen_mode
- 在布局预览中选择屏幕模式。
如果将 xml 文件中的片段添加到 FoldableLayout,将需要以下属性来预览片段 UI:
show_in_single_screen
show_in_dual_screen_start
show_in_dual_screen_end
show_in_dual_portrait_single_container
show_in_dual_landscape_single_container
容器 ID
容器具有 ID:
first_container_id
second_container_id
无论屏幕方向或设置的布局特殊行为是什么,如果布局仅显示一个容器,它的 ID 将是 first_container_id
。 如果它显示两个容器,则将是 second_container_id
。
例如:
- 如果应用程序处于单屏模式,则容器 ID 将是
first_container_id
。 - 如果已完成双纵向中向双屏模式的转换,且我们已设置
dual_portrait_single_layout_id
或is_dual_portrait_single_container
,则双屏模式中将仅有一个容器,它的 ID 将仍是first_container_id
。 - 如果已完成向双横向的转换,但我们没有设置属性
dual_landscape_single_layout_id
和is_dual_landscape_single_container
,则 ID 为first_container_id
和second_container_id
的两个容器都会存在。
在代码中创建 FoldableLayout
findViewById<FrameLayout>(R.id.parent).addView(
FoldableLayout(this, FoldableLayout.Config().apply {
singleScreenLayoutId = R.layout.single_screen
dualScreenStartLayoutId = R.layout.dual_screen_start
dualScreenEndLayoutId = R.layout.dual_screen_end
dualLandscapeSingleLayoutId = R.layout.single_screen
})
)
替换 FoldableLayout 配置
下面的代码将放弃旧配置,将其替换为新配置,并使用新配置来显示视图。
findViewById<FoldableLayout>(R.id.surface_duo_layout)
.newConfigCreator()
.singleScreenLayoutId(R.layout.single_screen)
.dualScreenStartLayoutId(R.layout.dual_screen_start)
.dualScreenEndLayoutId(R.layout.dual_screen_end)
.reInflate()
更新 FoldableLayout 配置
下面的代码将用所选属性更新当前配置,并显示视图:
findViewById<FoldableLayout>(R.id.surface_duo_layout)
.updateConfigCreator()
.dualScreenStartLayoutId(R.layout.dual_screen_start)
.reInflate()
如何使用布局组件
若要创建应用程序,可以使用某个活动或某个包含片段的活动来处理 UI。 也可在布局资源文件中声明片段,或者直接在活动中创建片段。 稍后我们将讨论组件如何处理这些情况。
使用活动
在这里,我们只使用一个活动来处理 UI,通过这种方式了解组件的工作原理。
首先,必须将
FoldableLayout
添加到活动的 *.xml 文件中。<com.microsoft.device.dualscreen.layouts.FoldableLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/enlightened_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:animateLayoutChanges="true" app:single_screen_layout_id="@layout/single_screen_layout" app:dual_screen_start_layout_id="@layout/single_screen_layout" app:dual_screen_end_layout_id="@layout/dual_screen_end_layout"/>
然后,创建三个适用于不同屏幕模式的布局。
将布局链接到活动。
使用在资源文件中声明的片段
在这里,我们将了解组件如何使用 *.xml 文件中声明的片段。
首先,必须将
FoldableLayout
添加到活动的 *.xml 文件中。<com.microsoft.device.dualscreen.layouts.FoldableLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" app:single_screen_layout_id="@layout/single_screen_layout" app:dual_screen_start_layout_id="@layout/dual_screen_start_layout" app:dual_screen_end_layout_id="@layout/dual_screen_end_layout" />
接下来,将片段声明到 singlescreenlayout.xml、dualscreenstartlayout.xml 和 dualscreenendlayout.xml 文件中。
<fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/single_list" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.microsoft.device.display.samples.contentcontext.MapPointListFragment" />
将布局链接到活动。
使用在活动中创建的片段
最后,我们将了解组件如何使用通过 getSupportFragmentManager().beginTransaction()
添加的片段。
首先,必须将
FoldableLayout
添加到活动的 *.xml 文件中。<com.microsoft.device.dualscreen.layouts.FoldableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" />
这会为视图创建容器,但不会将其放大。
可以使用容器 ID 访问
FoldableLayout
的容器:first_container_id
second_container_id
接下来,请访问片段管理器状态处理程序库,因为在处理屏幕模式转换时需要特别谨慎地处理片段。
查看绑定
重要
请使用 findViewById,如下面的代码片段中所示。 请勿尝试使用 Google View 绑定。
由于当 WindowManager
包含有关窗口布局的可用信息时 FoldableLayout
内容会膨胀,因此无法检索子实例并使用它。
为了绑定子视图,首先需要确保 FoldableLayout
内容已能够使用。
为此,应使用以下方法:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val contentChangedListener = object : FoldableLayout.ContentChangedListener {
override fun contentChanged(screenMode: ScreenMode?) {
// Here, you can retrieve the child instance
val child = binding.foldableLayout.findViewById<View>(R.id.child_view)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
override fun onResume() {
super.onResume()
binding.foldableLayout.addContentChangedListener(contentChangedListener)
}
override fun onPause() {
super.onPause()
binding.foldableLayout.removeContentChangedListener(contentChangedListener)
}
}
其中:
FoldableLayout.ContentChangedListener
是在FoldableLayout
内容膨胀后将要调用的回调。FoldableLayout.addContentChangedListener
将注册给定的FoldableLayout.ContentChangedListener
回调。foldableLayout.removeContentChangedListener
将取消注册给定的FoldableLayout.ContentChangedListener
回调。
重要
需要从 Activity
或 Fragment
中将此代码添加到 onResume
和 onPause
方法中,以避免内存泄漏。