【问题标题】:What is the best way to reference the same path twice in a SwiftUI View?在 SwiftUI 视图中两次引用同一路径的最佳方法是什么?
【发布时间】:2020-03-27 19:33:54
【问题描述】:

我正在尝试创建一个动态生成的按钮,该按钮使用相同的路径来绘制主要形状,然后绘制边框。完整代码如下。

我目前最好的方法两次调用按钮生成器,但由于它使用随机数据(设计约束),连续调用使用不同的数据,因此边框无法正确重叠按钮形状。见下图。

import SwiftUI

class ButtonPath {
    func points(height: Int) ->
        ((Int,Int),(Int,Int),(Int,Int),
         (Int,Int),(Int,Int),(Int,Int),
         (Int,Int),(Int,Int),(Int,Int),
         (Int,Int),(Int,Int),(Int,Int))
    {
        func rand() -> Int { Int.random(in: -5...5) }
        func r2(x: Int) -> Int { Int.random(in: -x...x) }
        let screen: CGRect = UIScreen.main.bounds
        let widthMx = CGFloat(0.9)
        let origin = (x:15, y:15)
        let width = Int(screen.width * widthMx)

        // Corner points
        let tl   = (x: origin.x + rand(),   y: origin.x + rand()) // tl = Top Left, etc.
        let tr   = (x: origin.x + width + rand(),      y: origin.y + rand())
        let bl   = (x: origin.x + rand(),   y: origin.y + height + rand())
        let br   = (x: origin.x + width + rand(),      y: origin.y + height + rand())

        // Arc controls, we're drawing a rectangle counter-clockwise from the top left
        let a1c1 = (x: origin.x + rand(),   y: Int(Double(origin.y+height+rand()) * 0.3)) // a1c1 = Arc 1 Control 1
        let a1c2 = (x: origin.x + rand(),   y: Int(Double(origin.y+height+rand()) * 0.6))
        let a2c1 = (x: Int(Double(origin.x+width+rand()) * 0.3), y: origin.y + height + rand())
        let a2c2 = (x: Int(Double(origin.x+width+rand()) * 0.6), y: origin.y + height + rand())
        let a3c1 = (x: origin.x + width + rand(),                y: Int(Double(origin.y + height+rand()) * 0.6))
        let a3c2 = (x: origin.x + width + rand(),                y: Int(Double(origin.y + height+rand()) * 0.3))
        let a4c1 = (x: Int(Double(origin.x+width+rand()) * 0.6), y: origin.y + rand())
        let a4c2 = (x: Int(Double(origin.x+width+rand()) * 0.6), y: origin.y + rand())

        return (
            t1: tl, tr: tr, b1: bl, br: br,
            a1c1: a1c1, a1c2: a1c2, a2c1: a2c1,
            a2c2:a2c2, a3c1:a3c1, a3c2:a3c2, a4c1:a4c1, a4c2:a4c2
        )
    }
    func path (height:Int) -> Path {
        let (tl, tr, bl, br, a1c1, a1c2, a2c1, a2c2, a3c1, a3c2, a4c1, a4c2) = points(height: height)
        let path1 = Path { path in
            path.move( to: CGPoint(x: tl.0, y: tl.1) )
            path.addCurve( to: CGPoint(x: bl.0, y: bl.1), control1: CGPoint(x: a1c1.0, y: a1c1.1), control2: CGPoint(x: a1c2.0, y: a1c2.1))
            path.addCurve( to: CGPoint(x: br.0, y: br.1), control1: CGPoint(x: a2c1.0, y: a2c1.1), control2: CGPoint(x: a2c2.0, y: a2c2.1))
            path.addCurve( to: CGPoint(x: tr.0, y: tr.1), control1: CGPoint(x: a3c1.0, y: a3c1.1), control2: CGPoint(x: a3c2.0, y: a3c2.1))
            path.addCurve( to: CGPoint(x: tl.0, y: tl.1), control1: CGPoint(x: a4c1.0, y: a4c1.1), control2: CGPoint(x: a4c2.0, y: a4c2.1))
        }
        return path1
    }
}

struct MyButton: View {
    var color: String
    var title: String
    var height: Int
    var path: (Path) {
        get { ButtonPath().path(height: height) }
    }
    var body: some View {
        VStack {
            ZStack {
                path.fill(Color(color))
                path.stroke(Color.white, lineWidth: 4).shadow(color: Color("gray4"), radius: 4, x: -10, y: -10)
                Text(self.title).font(.custom("Chaloops-Bold", size: 30)).tracking(5).shadow(radius: 2)
            }
            .foregroundColor(Color.white)
            .frame(height:130)
        }
    }
}

struct Button_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            MyButton(color: "red1", title: "SUBMIT", height: 100)
            MyButton(color: "blue1", title: "SUBMIT", height: 100)
            MyButton(color: "red1", title: "SUBMIT", height: 100)
            MyButton(color: "blue1", title: "SUBMIT", height: 100)
        }
    }
}

【问题讨论】:

    标签: swift swiftui swift5


    【解决方案1】:

    这是怎么做的

    变体 1:

    struct MyButton: View {
        var color: String
        var title: String
        var height: Int
    
        var body: some View {
            let path = ButtonPath().path(height: height)
            return VStack {
                ZStack {
                    path.fill(Color(color))
                    path.stroke(Color.white, lineWidth: 4).shadow(color: Color("gray4"), radius: 4, x: -10, y: -10)
                    Text(self.title).font(.custom("Chaloops-Bold", size: 30)).tracking(5).shadow(radius: 2)
                }
                .foregroundColor(Color.white)
                .frame(height:130)
            }
        }
    }
    

    变体 2:

    struct MyButton: View {
        var color: String
        var title: String
        var height: Int
    
        private let path: Path
    
        init(color: String, title: String, height: Int) {
            self.color = color
            self.title = title
            self.height = height
            self.path = ButtonPath().path(height: height)
        }
    
        var body: some View {
            VStack {
                ZStack {
                    path.fill(Color(color))
                    path.stroke(Color.white, lineWidth: 4).shadow(color: Color("gray4"), radius: 4, x: -10, y: -10)
                    Text(self.title).font(.custom("Chaloops-Bold", size: 30)).tracking(5).shadow(radius: 2)
                }
                .foregroundColor(Color.white)
                .frame(height:130)
            }
        }
    }
    

    【讨论】:

    • 非常感谢 Asperi!我从你的两个变种中学到了很多东西,我能够删除我丑陋的黑客。
    猜你喜欢
    • 2021-06-20
    • 1970-01-01
    • 2010-09-29
    • 2010-10-08
    • 2020-11-10
    • 2011-10-26
    • 2013-06-13
    • 2012-10-14
    相关资源
    最近更新 更多