自适应应用的通用方法
那么,你究竟**如何**将一个为传统移动设备设计的应用,使其在各种设备上都表现出色?需要哪些步骤?
谷歌工程师在处理大型应用方面经验丰富,他们推荐以下三步法。
步骤 1:抽象化
#首先,识别你计划使其动态化的组件。分析这些组件的构造函数,并抽象出可以共享的数据。
需要自适应的常见组件有:
- 对话框,包括全屏和模态对话框
- 导航 UI,包括导航栏和底部栏
- 自定义布局,例如“UI 区域是更高还是更宽?”
例如,在 `Dialog` 组件中,你可以共享包含对话框**内容**的信息。
或者,你可能希望在应用窗口较小时切换到 `NavigationBar`,在应用窗口较大时切换到 `NavigationRail`。这些组件可能会共享一个可导航目的地的列表。在这种情况下,你可能会创建一个 `Destination` 组件来保存这些信息,并指定 `Destination` 既有图标又有文本标签。
接下来,你将评估屏幕尺寸,以决定如何显示你的 UI。
步骤 2:测量
#你有两种方法来确定显示区域的大小:`MediaQuery` 和 `LayoutBuilder`。
MediaQuery
#过去,你可能使用 `MediaQuery.of` 来确定设备屏幕的大小。然而,如今的设备屏幕尺寸和形状多种多样,这种测试可能会产生误导。
例如,也许你的应用当前在一个大屏幕上占据一个小窗口。如果你使用 `MediaQuery.of` 方法并得出屏幕很小的结论(而实际上,应用显示在大屏幕上的一个微小窗口中),并且你将应用锁定为竖屏模式,这会导致应用的窗口锁定在屏幕中央,周围是黑色。这在大屏幕上绝不是理想的 UI。
请记住,`MediaQuery.sizeOf` 返回的是应用整个屏幕的当前大小,而不仅仅是单个组件的大小。
你有两种方法来测量屏幕空间。你可以使用 `MediaQuery.sizeOf` 或 `LayoutBuilder`,具体取决于你是想要整个应用窗口的大小,还是更局部的尺寸。
如果你的组件希望全屏显示,即使应用窗口很小,请使用 `MediaQuery.sizeOf`,以便你可以根据应用窗口本身的大小选择 UI。在上一节中,你希望根据整个应用窗口的大小行为进行调整,因此会使用 `MediaQuery.sizeOf`。
在 `build` 方法内部请求应用窗口的大小,例如 `MediaQuery.sizeOf(context)`,会导致给定的 `BuildContext` 在 `size` 属性发生任何变化时重新构建。
LayoutBuilder
#`LayoutBuilder` 与 `MediaQuery.sizeOf` 实现类似的目标,但有一些区别。
`LayoutBuilder` 不提供应用窗口的大小,而是提供父 `Widget` 的布局约束。这意味着你可以根据在组件树中添加 `LayoutBuilder` 的特定位置获取尺寸信息。此外,`LayoutBuilder` 返回 `BoxConstraints` 对象而不是 `Size` 对象,因此你将获得内容的有效宽度和高度范围(最小值和最大值),而不仅仅是固定大小。这对于自定义组件很有用。
例如,想象一个自定义组件,你希望其尺寸基于专门分配给该组件的空间,而不是整个应用窗口。在这种情况下,请使用 `LayoutBuilder`。
步骤 3:分支
#此时,你必须决定在选择显示哪个版本的 UI 时使用哪些尺寸断点。例如,[Material 布局](https://m3.material.io/foundations/layout/applying-layout/window-size-classes)指南建议对于宽度小于 600 逻辑像素的窗口使用底部导航栏,对于宽度等于或大于 600 像素的窗口使用导航轨。再次强调,你的选择不应取决于设备的**类型**,而应取决于设备的可用窗口大小。
要通过一个在 `NavigationRail` 和 `NavigationBar` 之间切换的示例,请查看 [使用 Material 3 构建动画自适应应用布局](https://codelabs.developers.google.com/codelabs/flutter-animated-responsive-layout)。
下一页讨论如何确保你的应用在大屏幕和可折叠设备上看起来最佳。