SwiftUI:路径.anchorPreference

时间:2019-12-16 20:01:56

标签: swiftui

我正在尝试将SwiftUI路径.anchorPreference设置为居中。

我看过许多关于SO的示例,但无法使其正常工作。 Apple文档对此为零。

import SwiftUI

struct PatternScene: View {

    let pattern = Path { path in
        path.move(to: CGPoint(x: 50, y: 50))
        path.addLine(to: CGPoint(x: 250, y: 50))
        path.addLine(to: CGPoint(x: 250, y: 250))
        path.addLine(to: CGPoint(x: 50, y: 250))
        path.addLine(to: CGPoint(x: 100, y: 100))
    }

    var body: some View {
        self.pattern
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
            //.anchorPreference(key: <#T##PreferenceKey.Protocol#>, value: <#T##Anchor<A>.Source#>) { anchor in}
    }

}

struct PatternScene_Previews: PreviewProvider {
    static var previews: some View {
        PatternScene()
    }
}

感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

您需要创建符合struct的数据和密钥PreferenceKey才能使.anchorPreference(...)起作用:

类似这样的东西:

struct MyTextPreferenceData {
    let viewIdx: Int
    let bounds: Anchor<CGRect>
}

struct MyTextPreferenceKey: PreferenceKey {
    typealias Value = [MyTextPreferenceData]

    static var defaultValue: [MyTextPreferenceData] = []

    static func reduce(value: inout [MyTextPreferenceData], nextValue: () -> [MyTextPreferenceData]) {
        value.append(contentsOf: nextValue())
    }
}

struct PatternScene: View {
    let idx: Int

    let pattern = Path { path in
        path.move(to: CGPoint(x: 50, y: 50))
        path.addLine(to: CGPoint(x: 250, y: 50))
        path.addLine(to: CGPoint(x: 250, y: 250))
        path.addLine(to: CGPoint(x: 50, y: 250))
        path.addLine(to: CGPoint(x: 100, y: 100))
    }

    var body: some View {
        self.pattern
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
            .anchorPreference(key: MyTextPreferenceKey.self, value: .bounds, transform: { [MyTextPreferenceData(viewIdx: self.idx, bounds: $0)] })
    }
}

struct PatternScene_Previews: PreviewProvider {
    static var previews: some View {
        PatternScene(idx: 0)
    }
}

答案 1 :(得分:1)

这是方法的演示

SwiftUI Anchor center usage

测试代码:

struct TestPatternScene: View {
    var body: some View {
        VStack {
            PatternScene()
                .overlayPreferenceValue(PatternSceneCenterKey.self) { pref in
                    GeometryReader { g in
                        if pref.center != nil {
                            Circle()
                                .fill(Color.red)
                                .frame(width: 4, height: 4)
                                .position(g[pref.center!]) // !! read stored center point (already converted into .local space)
                        }
                    }
            }
            Spacer()
        }
    }
}

主要代码:

struct PatternSceneCenter { // Pref value to store anchor
    var center: Anchor<CGPoint>? = nil
}

struct PatternSceneCenterKey: PreferenceKey { // Pref key 
    typealias Value = PatternSceneCenter

    static var defaultValue: PatternSceneCenter = PatternSceneCenter()

    static func reduce(value: inout PatternSceneCenter, 
        nextValue: () -> PatternSceneCenter) {
        value = nextValue()
    }
}

struct PatternScene: View {

    let pattern = Path { path in
        path.move(to: CGPoint(x: 50, y: 50))
        path.addLine(to: CGPoint(x: 250, y: 50))
        path.addLine(to: CGPoint(x: 250, y: 250))
        path.addLine(to: CGPoint(x: 50, y: 250))
        path.addLine(to: CGPoint(x: 100, y: 100))
    }

    var body: some View {
        self.pattern
            .fill(Color.yellow)
            .frame(minWidth: 0, maxWidth: 100, minHeight: 0, maxHeight: 100)
            .anchorPreference(key: PatternSceneCenterKey.self, 
                value: .center) { PatternSceneCenter(center: $0) } // store center anchor of current view into our custom pref value
    }

}