Skip to content

使用 AnchorPreferences 进行几何对齐

探索 AnchorPreferences 的奥秘 🚀

AnchorPreferences 是 SwiftUI 中一个强大的工具,它允许你从子视图向父视图传递几何信息,实现视图间的精确对齐。这在创建复杂布局时非常有用,例如,你需要将一个视图的边缘与另一个视图的特定位置对齐。使用 AnchorPreferences,你可以轻松地实现这种对齐,而无需手动计算位置。

AnchorPreferences 的核心在于 PreferenceKey 协议。你需要创建一个自定义的 PreferenceKey,用于存储你想要传递的锚点信息。锚点可以是视图的任何几何属性,例如中心点、边缘或大小。

如何使用 AnchorPreferences 🛠️

  1. 定义一个 PreferenceKey: 首先,你需要定义一个 PreferenceKey 来存储锚点信息。这个 PreferenceKey 必须有一个关联类型,用于指定锚点信息的类型。例如,如果你想传递视图的中心点,你可以使用 CGPoint 作为关联类型。

    swift
    struct MyAnchorKey: PreferenceKey {
        static var defaultValue: Anchor<CGPoint>? { nil }
        static func reduce(value: inout Anchor<CGPoint>?, nextValue: () -> Anchor<CGPoint>?) {
            value = nextValue()
        }
    }
  2. 使用 anchorPreference 修饰符: 使用 anchorPreference 修饰符将锚点信息附加到视图上。这个修饰符接受两个参数:一个键和一个锚点。键是你定义的 PreferenceKey,锚点是你想要传递的几何属性。

    swift
    Text("Hello, world!")
        .anchorPreference(key: MyAnchorKey.self, value: .center) { anchor in
            anchor
        }
  3. 使用 onPreferenceChange 修饰符: 在父视图中使用 onPreferenceChange 修饰符来接收锚点信息。这个修饰符接受两个参数:一个键和一个闭包。键是你定义的 PreferenceKey,闭包会在锚点信息发生变化时被调用。

    swift
    @State private var myAnchor: Anchor<CGPoint>?
    
    var body: some View {
        VStack {
            Text("Parent View")
            Text("Hello, world!")
                .anchorPreference(key: MyAnchorKey.self, value: .center) { anchor in
                    anchor
                }
        }
        .onPreferenceChange(MyAnchorKey.self) { anchor in
            myAnchor = anchor
        }
    }

实例演示:精准对齐 🎯

假设你想要将一个按钮与另一个视图的底部对齐。你可以使用 AnchorPreferences 来实现这个目标。首先,你需要定义一个 PreferenceKey 来存储视图底部的锚点信息。然后,你可以使用 anchorPreference 修饰符将锚点信息附加到视图上。最后,你可以在父视图中使用 onPreferenceChange 修饰符来接收锚点信息,并使用它来对齐按钮。

swift
struct BottomAnchorKey: PreferenceKey {
    static var defaultValue: Anchor<UnitPoint>? { nil }
    static func reduce(value: inout Anchor<UnitPoint>?, nextValue: () -> Anchor<UnitPoint>?) {
        value = nextValue()
    }
}

struct ContentView: View {
    @State private var bottomAnchor: Anchor<UnitPoint>?

    var body: some View {
        VStack {
            Text("Top View")
                .background(GeometryReader { proxy in
                    Color.clear
                        .anchorPreference(key: BottomAnchorKey.self, value: .bottom) { anchor in
                            anchor
                        }
                })
            Button("Bottom Button") {
                // Action
            }
            .alignmentGuide(.top) { dimension in
                if let anchor = bottomAnchor {
                    return dimension[anchor]
                } else {
                    return dimension[.top]
                }
            }
        }
        .onPreferenceChange(BottomAnchorKey.self) { anchor in
            bottomAnchor = anchor
        }
    }
}

总结 🎉

AnchorPreferences 是一个强大的工具,可以帮助你创建复杂的布局。通过使用 PreferenceKeyanchorPreferenceonPreferenceChange 修饰符,你可以轻松地从子视图向父视图传递几何信息,并使用它来实现视图间的精确对齐。掌握 AnchorPreferences 将使你能够构建更灵活、更强大的 SwiftUI 应用程序。 记住,实践是最好的老师! 动手尝试一下,你会发现 AnchorPreferences 的强大之处。

本站使用 VitePress 制作