跳到主内容

自适应设计的最佳实践

自适应设计的部分最佳实践总结。

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

设计考量

#

拆分你的组件

#

在设计应用时,尝试将大型、复杂的组件拆分为更小、更简单的组件。

重构组件可以通过共享核心代码片段来降低采用自适应 UI 的复杂度。这样做还有其他好处:

  • 在性能方面,拥有许多小的 const 组件比拥有大型、复杂的组件能改善重建时间。
  • Flutter 可以重用 const 组件实例,而大型复杂组件则必须在每次重建时重新设置。
  • 从代码健康的角度来看,将 UI 组织成更小、易于管理的块有助于降低每个 Widget 的复杂度。复杂度较低的 Widget 更易读、更易重构,且不太可能出现意外行为。

要了解更多信息,请查看通用方法中的自适应设计 3 个步骤。

针对每种外形规格的优势进行设计

#

除了屏幕尺寸,你还应该花时间考虑不同外形规格的独特优势和劣势。对于跨平台应用来说,在所有地方提供完全相同的功能并不总是理想的选择。考虑是否需要针对特定设备类别专注于特定能力,甚至移除某些功能。

例如,移动设备便于携带且配有摄像头,但它们并不适合进行详细的创意工作。考虑到这一点,你可能会在移动端 UI 中更专注于捕捉内容并添加位置数据标签,而在平板电脑或桌面端 UI 中则专注于组织或处理这些内容。

另一个例子是利用 Web 极低的分享门槛。如果你正在部署 Web 应用,请决定要支持哪些深度链接 (deep links),并据此设计你的导航路由。

这里的关键点是思考每个平台最擅长什么,并观察是否有你可以利用的独特能力。

优先解决触摸交互

#

构建优秀的触摸 UI 通常比传统桌面 UI 更困难,这部分原因在于缺乏右键点击、滚轮或键盘快捷键等输入加速器。

应对这一挑战的一种方法是优先专注于打造出色的触摸式 UI。你仍然可以使用桌面目标进行大部分测试以获得迭代速度,但记得要经常切换到移动设备,以验证一切操作感觉是否正确。

在打磨好触摸界面后,你可以针对鼠标用户调整视觉密度,然后叠加所有额外的输入。将这些其他输入视为加速器——即能加快任务执行速度的替代方案。需要考虑的重要一点是,用户在使用特定输入设备时会有何预期,并努力在你的应用中体现出来。

实现细节

#

不要锁定应用的屏幕方向。

#

自适应应用应该在不同尺寸和形状的窗口中看起来都很美观。虽然在手机上将应用锁定为纵向模式有助于缩小最小可行性产品 (MVP) 的范围,但这会增加未来使应用实现自适应的成本。

例如,认为手机只会在全屏纵向模式下渲染你的应用是不准确的。多窗口应用支持正变得普遍,折叠屏设备也有许多在多应用并排运行时效果最好的使用场景。

如果你绝对必须锁定应用的纵向模式(但其实不建议这样做),请使用 Display API 而不是 MediaQuery 之类的方法来获取屏幕的物理尺寸。

总结

避免基于设备方向进行布局

#

避免在组件树的顶层使用 MediaQuery 的 orientation 字段或 OrientationBuilder 来切换不同的应用布局。这类似于不应为了确定屏幕尺寸而检查设备类型的指导原则。设备的方向并不一定能告诉你应用窗口拥有多少空间。

相反,请使用 MediaQuerysizeOfLayoutBuilder,如通用方法页面所述。然后使用 Material 推荐的那种自适应断点。

不要占用所有水平空间

#

当在宽屏设备上运行时,那些使用窗口全宽来显示框或文本域的应用通常表现不佳。

要了解如何避免这种情况,请查看使用 GridView 布局

避免检查硬件类型

#

在进行布局决策时,避免编写检查设备是否为“手机”或“平板电脑”或任何其他特定设备类型的代码。

应用实际获得的渲染空间并不总是与设备的整个屏幕尺寸挂钩。Flutter 可以在许多不同平台上运行,你的应用可能正在 ChromeOS 上以可调整大小的窗口运行,可能在平板电脑的多窗口模式下与另一个应用并排运行,甚至是在手机的画中画模式中运行。因此,设备类型与应用窗口大小之间并没有很强的关联。

相反,请使用 MediaQuery 来获取应用当前运行所在的窗口大小。

这不仅对 UI 代码有帮助。要了解抽象出设备能力如何帮助你的业务逻辑代码,请查看 2022 年 Google I/O 大会的演讲:Flutter 联合插件开发经验教训

支持各种输入设备

#

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

Material 库提供了在触摸、鼠标和键盘交互方面具有出色默认行为的组件。

要了解如何为自定义组件添加此支持,请查看用户输入与无障碍性

恢复列表状态

#

要在设备方向改变时保持列表的滚动位置且不改变布局,请使用 PageStorageKey 类。当组件被销毁时,PageStorageKey 会将组件状态持久化到存储中,并在组件重建时恢复该状态。

你可以在 Wonderous 应用中看到此示例,它将列表的状态存储在 SingleChildScrollView 组件中。

如果 List 组件在设备方向改变时会更改布局,你可能需要进行一些数学计算(示例)来调整屏幕旋转后的滚动位置。

保存应用状态

#

当设备旋转、更改窗口大小或进行折叠/展开时,应用应保留或恢复应用状态。默认情况下,应用应该维护状态。

如果你的应用在设备配置更改期间丢失了状态,请验证应用所使用的插件和原生扩展是否支持该设备类型(例如大屏设备)。某些原生扩展在设备位置改变时可能会丢失状态。

关于此情况的真实案例,请参阅 Medium 上的免费文章《开发 Flutter 大屏应用》中的问题:折叠/展开导致状态丢失部分。