Anchors
在布局层次结构的不同部分之间传递点和矩形时,锚点非常有用。锚点是围绕值(例如,点)的包装,可以在视图层次结构中其他位置的不同视图的坐标系统内解析该值。我们可以将锚视为UIKit中UIView的convert(_:from :)方法的更安全替代方法.
例如,让我们考虑一个简单的标签栏组件,在其中我们可能希望显示许多标签(以文本表示)。所选选项卡应带有下划线。当用户点击一个新选项卡时,我们要为下划线的位置和宽度设置动画。这意味着下划线将不会成为标签项的一部分,而是会在视图层次结构中的其他位置绘制。我们可以使用锚点(通过首选项)传达所选选项卡的位置,并在视图层次结构的不同部分解析锚点.
我们将使用ForEach在HStack中呈现选项卡。所选项目将使用首选项传播其边界(作为Anchor<CGRect>)。在视图层次结构的更上方,我们可以读出所选项目的锚点并在该位置画一条线。第一步,我们需要一个自定义的首选项键。 BoundsKey与上面的WidthKey相似,它返回第一个非null值:
struct BoundsKey: PreferenceKey {
static var defaultValue: Anchor<CGRect>? = nil
static func reduce(
value: inout Anchor<CGRect>?,
nextValue: () -> Anchor<CGRect>?) {
value = value ?? nextValue()
}
}
这是在HStack中绘制项目并提供锚点的代码。我们向按钮添加anchorPreference,并使用.bounds作为值。 anchorPreference修饰符还采用了一个转换函数,该函数使我们可以将锚点转换为不同的东西。在我们的例子中,我们将其转换为可选的锚点(除非选择了当前项,否则它将为nil)