跳到主内容

SafeArea 与 MediaQuery

了解如何使用 SafeArea 和 MediaQuery 来创建自适应应用。

本页讨论如何以及何时使用 SafeAreaMediaQuery 组件。

SafeArea

#

在最新设备上运行应用时,您可能会遇到 UI 被屏幕上的缺口(如刘海屏、摄像头孔)遮挡的情况。您可以使用 SafeArea 组件来解决此问题。它会为其子组件添加内边距(inset),以避开这些侵入性区域,同时也能避开操作系统 UI(如 Android 上的状态栏)或物理显示屏的圆角。

如果您不需要这种行为,SafeArea 组件允许您禁用四个边中任意一边的内边距。默认情况下,四个边都已启用。

通常建议将 Scaffold 组件的 body 包裹在 SafeArea 中作为起步,但并不总是需要将其放在组件树中如此高的位置。

例如,如果您有意让应用延伸到缺口下方,您可以将 SafeArea 移动到仅包裹特定的相关内容,并让应用的其余部分全屏显示。

使用 SafeArea 可以确保您的应用内容不会被物理显示特征或操作系统 UI 遮挡,并为您的应用做好准备,即使未来市场出现各种形状和样式的新设备,您的应用也能保持良好的显示效果。

SafeArea 是如何用少量代码实现这么多功能的呢?在后台,它使用了 MediaQuery 对象。

MediaQuery

#

正如 SafeArea 部分所讨论的,MediaQuery 是创建自适应应用的强大组件。有时您会直接使用 MediaQuery,有时则会使用在后台调用了 MediaQuerySafeArea

MediaQuery 提供了大量信息,包括应用当前的窗口大小。它还公开了辅助功能设置,例如高对比度模式、文本缩放,以及用户是否正在使用 TalkBack 或 VoiceOver 等辅助功能服务。MediaQuery 还包含有关设备显示特性的信息,例如是否有铰链或折叠屏。

SafeArea 使用来自 MediaQuery 的数据来计算为其子 Widget 添加多少内边距。具体来说,它使用了 MediaQuery 的 padding 属性,这基本上就是显示屏被系统 UI、屏幕缺口或状态栏遮挡的部分。

那么,为什么不直接使用 MediaQuery 呢?

答案是 SafeArea 做了一件巧妙的事情,使其比单纯使用原始的 MediaQueryData 更具优势。具体而言,它修改了传递给 SafeArea 子组件的 MediaQuery,使其看起来好像 SafeArea 所添加的内边距并不存在。这意味着您可以嵌套使用 SafeArea,并且只有最外层的那一个会应用避开缺口和系统 UI 所需的内边距。

随着应用的增长和组件的迁移,如果您嵌套了多个 SafeArea,也无需担心应用了过多的内边距;而如果直接使用 MediaQueryData.padding,则会遇到这类问题。

可以SafeArea 包裹 Scaffold 组件的 body,但不一定要把它放在组件树中如此高的位置。SafeArea 只需要包裹那些如果被上述硬件特性遮挡会导致信息丢失的内容即可。

例如,如果您有意让应用延伸到缺口下方,您可以将 SafeArea 移动到仅包裹特定的相关内容,并让应用的其余部分全屏显示。顺便提一下,AppBar 组件默认就是这样做的,这就是它能够延伸到系统状态栏下方的原理。这也是为什么建议将 Scaffold 的 body 包裹在 SafeArea 中,而不是直接包裹整个 Scaffold 的原因。

SafeArea 以通用方式确保您的应用内容不会被遮挡,即使未来市场出现各种形状和样式的新设备,您的应用也能保持良好的显示效果。