SwiftUI 披萨按钮

Spr*_*ite 2 swift swiftui

我想知道是否可以创建所谓的“披萨按钮”,它本身就是一个圆形视图,对角线分为 4 半(按钮),中间还有一个按钮。每一块都应该是可点击的

ZStack 不起作用,因为只有顶部按钮视图是可单击的。请给我一个建议,我该怎么做。

“披萨按钮”

我的测试代码:和资产

struct FirstView: View {
    var body: some View {
        VStack {
            HStack {
                Button(action: {
                    
                }, label: {
                    Text("Menu")
                        .frame(width: 88, height: 44)
                        .background(.gray)
                        .cornerRadius(12)
                })
                
                Spacer()
                
                Button(action: {
                    
                }, label: {
                    Text("Settings")
                        .frame(width: 88, height: 44)
                        .background(.gray)
                        .cornerRadius(12)
                })
                
              
            }
            .padding(.horizontal, 40)
            
            ZStack {
    
                Button(action: {
                    print("1")
                }, label: {
                    Image("left_btn")
                        .resizable()
                        .scaledToFit()
                        .border(.green)
                        .frame(width: 215, height: 215)
                        .edgesIgnoringSafeArea(.all)
                })
                
                Button(action: {
                    print("2")
                }, label: {
                    Image("top_btn")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 215, height: 215)
                        .edgesIgnoringSafeArea(.all)
                        .ignoresSafeArea()
                        .border(.yellow)
                })
               

                Button(action: {
                    print("3")
                }, label: {
                    Image("right_btn")
                        .resizable()
                        .frame(width: 215, height: 215)
                        .border(.purple)
                })

                Button(action: {
                    print("4")
                }, label: {
                    Image("bottom_btn")
                        .resizable()
                        .frame(width: 215, height: 215)
                        .border(.blue)
                })
                
                Button(action: {
                    print("5")
                }, label: {
                    Image("center_btn")
                        .resizable()
                        .frame(width: 87, height: 87)
                        .border(.orange)
                })
            }
        }
        .background(.red)
    }
}
Run Code Online (Sandbox Code Playgroud)

左边 中心 正确的 [顶部5 ] 左边

gra*_*irr 6

正如评论中所讨论的,使用资产并不是解决这个问题的正确方法。

我曾经ArcsPizza ShapesSFSymbols为箭头图像。

它看起来是这样的: 比萨

Pizza Shapes有响应,但小圆圈没有响应,但您可以使用轻松修复此问题GeometryReader

代码:


import SwiftUI

struct ContentView: View {
    @State private var clicked = false
    var body: some View
    {
        ZStack {
            Color.brown.ignoresSafeArea()
            ZStack(alignment: .center) {
                Group {
                    PizzaButton(type: .down)
                        .foregroundColor(clicked ? .teal : .white)
                        .opacity(clicked ? 0.7 : 1)
                        .onTapGesture {
                            print("click")
                            clicked.toggle()
                            
                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                                clicked = false
                            }
                        }
                    PizzaButton(type: .up)
                    PizzaButton(type: .left)
                    PizzaButton(type: .right)
                }
                .foregroundColor(.white)
                .animation(.interactiveSpring(), value: clicked)
                Circle()
                    .frame(width: 120, height: 120, alignment: .center) // you can use GeometryReader to make these sizes responsive.
                    .foregroundColor(.init(white: 0.98))
                Circle()
                    .strokeBorder(lineWidth: 4)
                    .frame(width: 30, height: 30, alignment: .center)
                    .foregroundColor(.init(white: 0.28))
            }
            .frame(width: 400, height: 400, alignment: .center)
        }
    }
}

struct PizzaButton : View {
    let type : ButtonType
    let alignment : Alignment
    let edge : Edge.Set
    let arrowDirection : String
    
    init (type : ButtonType) {
        self.type = type
        switch (type) {
        case .up:
            alignment = .top
            edge = .top
            arrowDirection = "up"
        case .right:
            alignment = .trailing
            edge = .trailing
            arrowDirection = "forward"
        case .left:
            alignment = .leading
            edge = .leading
            arrowDirection = "backward"
        case .down:
            alignment = .bottom
            edge = .bottom
            arrowDirection = "down"
        }
    }
    var body: some View {
        GeometryReader { geo in
            ZStack(alignment: alignment) {
                PizzaButtonShape(type: type)
                    .stroke(lineWidth: 1)
                    .background(PizzaButtonShape(type: type)) // this is required because .stroke clears the shapes background.
                Image(systemName: "arrow.\(arrowDirection)")
                    .foregroundColor(.init(white: 0.35))
                    .font(.largeTitle)
                    .padding(edge, geo.size.width / 5)
            }
        }
    }
}

struct PizzaButtonShape : Shape {
    let type : ButtonType
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let startAngle : Angle
        let endAngle : Angle
        
        switch(type) {
        case .up:
            startAngle = .degrees(225)
            endAngle = .degrees(315)
            break
        case .down:
            startAngle = .degrees(45)
            endAngle = .degrees(135)
            break
        case .right:
            startAngle = .degrees(315)
            endAngle = .degrees(45)
            break
        case .left:
            startAngle = .degrees(135)
            endAngle = .degrees(225)
            break
        }
        
        path.move(to: CGPoint(x: rect.midX, y: rect.midY))
        
        path.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.height / 3, startAngle: startAngle, endAngle: endAngle, clockwise: false)
        
        return path
    }
}

enum ButtonType {
    case left, right, up, down
}
Run Code Online (Sandbox Code Playgroud)