跳转至正文

自适应设计最佳实践

自适应设计部分最佳实践摘要。

自适应设计的推荐最佳实践包括:

设计考量

#

拆分 widget

#

设计应用时,尽量将大型、复杂的 widget 拆分为更小、更简单的 widget。

重构 widget 可通过共享核心代码降低采用自适应 UI 的复杂度,还有其他好处:

  • On the performance side, having lots of small const widgets improves rebuild times over having large, complex widgets.

  • Flutter can reuse const widget instances, while a larger complex widget has to be set up for every rebuild.

  • From a code health perspective, organizing your UI into smaller bite sized pieces helps keep the complexity of each Widget down. A less-complex Widget is more readable, easier to refactor, and less likely to have surprising behavior.

  • 在性能方面,大量小型 const widget 比大型复杂 widget 更能缩短重建时间。

  • Flutter 可复用 const widget 实例,而较大的复杂 widget 每次重建都需重新设置。

  • 从代码健康角度看,将 UI 组织成更小的片段有助于降低每个 Widget 的复杂度。复杂度较低的 Widget 更易读、更易重构,也更少出现意外行为。

要了解更多,请参阅 General approach 中的自适应设计三步法。

针对各形态优势进行设计

#

除屏幕尺寸外,你还应花时间考虑不同形态的独特优势与劣势。多平台应用并非在所有地方提供完全相同功能总是理想选择。考虑是否在某些设备类别上聚焦特定能力,甚至移除某些功能。

例如,移动设备便携且带相机,但不适合精细创意工作。据此,移动 UI 可更侧重内容采集与位置标记,平板或桌面 UI 则侧重组织或编辑该内容。

另一例是利用 Web 极低的分享门槛。若部署 Web 应用,决定支持哪些深度链接,并据此设计导航路由。

要点是思考各平台最擅长什么,以及能否利用独特能力。

先解决触控

#

构建出色的触控 UI 往往比传统桌面 UI 更难,部分原因是缺少右键、滚轮或键盘快捷键等输入加速器。

一种应对方式是先聚焦出色的触控导向 UI。你仍可用桌面目标做大部分测试以加快迭代,但请经常切换到移动设备验证体验是否合适。

触控界面打磨好后,可为鼠标用户调整视觉密度,再叠加其他输入。将这些输入视为加速器——让任务更快的替代方式。重要的是考虑用户使用特定输入设备时的预期,并在应用中体现。

实现细节

#

不要锁定应用方向。

#

自适应应用应在不同尺寸和形状的窗口上表现良好。在手机上锁定竖屏有助于缩小最小可行产品范围,但会增加日后实现自适应的工作量。

例如,手机仅以全屏竖屏渲染应用并非必然。多窗口应用支持日益普遍,折叠屏也有许多适合多应用并排的场景。

若必须锁定竖屏(但最好不要),请使用 Display API 而非 MediaQuery 等方式获取屏幕物理尺寸。

总结如下:

避免基于设备方向的布局

#

避免在 widget 树顶部附近使用 MediaQuery 的 orientation 字段或 OrientationBuilder 在不同应用布局间切换。这与不要通过设备类型判断屏幕尺寸的建议类似。设备方向也未必告诉你应用窗口有多少空间。

请改用 MediaQuerysizeOfLayoutBuilder,如 General approach 页所述。然后使用 Material 推荐的自适应断点等。

不要占满全部横向空间

#

在大屏上运行时,用窗口全宽显示方框或文本字段的应用体验不佳。

要了解如何避免,请参阅 Layout with GridView

避免检查硬件类型

#

避免在布局决策时编写代码判断运行设备是「手机」「平板」或其他类型。

应用实际获得的渲染空间未必与设备全屏尺寸挂钩。Flutter 可在多种平台运行,应用可能在 ChromeOS 的可调整窗口、平板多窗口并排,甚至手机画中画中运行。因此设备类型与应用窗口尺寸并无强关联。

请改用 MediaQuery 获取应用当前运行窗口的尺寸。

这不仅对 UI 代码有帮助。要了解抽象设备能力如何帮助业务逻辑,请参阅 2022 Google I/O 演讲 Flutter lessons for federated plugin development

支持多种输入设备

#

应用应支持基本鼠标、触控板和键盘快捷键。最常见用户流程应支持键盘导航以确保无障碍。尤其在大屏设备上,应用应遵循键盘相关的无障碍最佳实践。

Material 库提供的 widget 在触控、鼠标和键盘交互方面有出色的默认行为。

要了解如何为自定义 widget 添加此类支持,请参阅 User input & accessibility

恢复 List 状态

#

要在设备方向改变时布局不变的列表中保持滚动位置,请使用 PageStorageKey 类。PageStorageKey 在 widget 销毁后将状态持久化,并在重建时恢复。

可在 Wonderous app 中查看示例,它在 SingleChildScrollView widget 中保存列表状态。

List widget 在方向改变时改变布局,屏幕旋转时可能需要一些计算(示例)来调整滚动位置。

保存应用状态

#

应用应在设备旋转、窗口尺寸变化或折叠/展开时保留或恢复应用状态。默认情况下,应用应维持状态。

若应用在设备配置变更时丢失状态,请确认所用插件和原生扩展是否支持该设备类型(例如大屏)。部分原生扩展在设备姿态变化时可能丢失状态。

有关此类真实案例的更多信息,请参阅 Medium 免费文章 Developing Flutter apps for Large screens 中的 Problem: Folding/unfolding causes state loss