本系列教程基于Flutter widget, 意在为Flutter 入门提供基础建设. 重点在讲解widget 的 用法,参数以及扩展.
适宜人群: 入门

引子

SafeArea 用于填充类似于刘海屏、异形屏之类的屏幕的边距, 在其中加入 padding . 保证多端多设备中展示不受影响. 同时, 这样操作也可以保证在多数情况下. 跨平台多端设备ui保持一致.

SafeArea

SafeArea 参数包括:

image
其中 left、top、right、bottom 代表着四周是否需要有安全距离. minimum 代表着最小填充距离, maintainBottomViewPadding 代表着是否需要底部视图填充,

这几个参数构成了 SafeArea 可以隔离异形屏导致的 ui 问题. 实际上 SafeArea 也是一个 StatelessWidget , 它本身也不用主动去更新 ui . 它做的仅仅是包裹了一层 Padding 和 MediaQuery.removePadding.

image
可能大家会疑惑, 这怎么增加了 Padding 又 remove 了 Padding 呢? 实际上此 Padding 非彼 Padding . 在外层的 Padding 是填充了被异形屏所遮挡的部分, 而内部的 removePadding 则是把这部分的填充距离给去掉, 这样后续 child 获取外部 Padding 的时候就不会再重复获取多余的 Padding 了.

填充

我们聚焦一下 SafeArea 是如何通过 Padding 来解决异形屏导致的 ui 问题. 在 build 方法中, SafeArea 首先获取了系统提供的 MediaQueryData 的数据. 这里包含了屏幕相关的一些数据. 我们取到相关的 padding 值 , 这里的 padding 即异形屏导致的需要填充部分. 那么, 内部的 Padding 控件是如何处理的呢?

1
2
3
4
5
6
padding: EdgeInsets.only(
left: math.max(left ? padding.left : 0.0, minimum.left),
top: math.max(top ? padding.top : 0.0, minimum.top),
right: math.max(right ? padding.right : 0.0, minimum.right),
bottom: math.max(bottom ? padding.bottom : 0.0, minimum.bottom),
)

这里首先根据用户传进的参数判断是否增加对应边的填充物. 如果需要填充则会返回相应的填充间距. 在取得间距后, 如果用户有传最小的 minimum 值. 那么最终结果在取决于 minimum 和间距, 二者谁大则最终会返回相应的结果. 至此, SafeArea 也就完成了相应的间距填充, 维护了跨平台多设备的ui一致性.

思考

SafeArea 本质上是一个通过 Padding 以及 MediaQuery 组合的一个无状态组件, 通过对它的使用, 希望可以让你加深无状态组件的理解. 同时, MediaQuery 能够提供数据的根本原因是它是一个 InheritedWidget . 所以我们在更改其中一个节点数据时, 将会影响到后续子节点的调用. 这里也在 SafeArea 对 MediaQuery 的调用中有所体现. 由小窥大! 希望大家都可以在源码中有所收获, 获得成长!

这里是WeninerIo😇

如果你对这次的技术分享感兴趣或者有什么疑惑🧐

不妨在评论区留言或私信🤪

或许这次的分享不是你所期待的😣

那就点个关注吧! 🙏

下次也许就是你中意的呢🫣?