SwiftUI 拖动手势坐标

2024-03-28

我正在尝试向我正在编写的应用程序添加评级系统。我的方法不太优雅,使用Stepper。如果可能的话,我想要一种交互式拖动方式来填充星级。

我不确定是否DragGesture是我正在寻找的,这足够吗?另外,我不确定如何将坐标转换为正确的宽度以填充星星。任何帮助,将不胜感激。

struct ContentView: View {
    @State var rating: Double = 0.0

    var body: some View {
        VStack {
            HStack(spacing: 3) {
                let stars = HStack(spacing: 0) {
                    ForEach(0..<5) { _ in
                        Image(systemName: "star.fill")
                            .font(.title3)
                    }
                }
                stars.overlay(
                    GeometryReader { geometry in
                        ZStack(alignment: .leading) {
                            Rectangle()
                                .frame(width: CGFloat(rating / 2) / 5 * geometry.size.width)
                                .foregroundColor(Color.yellow)
                        }
                    }.mask(stars)
                ).foregroundColor(Color.secondary)
            }
            Stepper("Rating \(String(format: "(%.0f%%)", rating * 10))", value: $rating, in: 0...10, step: 0.5)
        }
        .padding()
        
        Spacer()
            .frame(height: 100)
        HStack(spacing: 3) {
            let stars = HStack(spacing: 0) {
                ForEach(0..<5) { _ in
                    Image(systemName: "star.fill")
                        .font(.title3)
                }
            }
            stars.overlay(
                GeometryReader { geometry in
                    ZStack(alignment: .leading) {
                        Rectangle()
                            .frame(width: CGFloat(rating / 2) / 5 * geometry.size.width)
                            .foregroundColor(Color.yellow)
                    }
                }.mask(stars)
            ).foregroundColor(Color.secondary)
                .gesture(
                    DragGesture(minimumDistance: 0)
                        .onEnded { end in
                            if (end.location.x - end.startLocation.x) > 0 {
                                print("Right")
                            } else {
                                print("Left")
                            }
                        })
        }
    }
}

我使用圆形作为剪辑形状,但其余的应该做你想要的。 如果将 @State 评级更改为 @Binding,则可以将其称为子视图。

struct ContentView: View {
    
    @State var rating = 50.0
    
    var body: some View {
        VStack {
            Text("Your Rating \(rating, specifier: "%.0f")")
            
            GeometryReader { geo in
                HStack(spacing: 0) {
                    Color.yellow
                        .frame(width: geo.size.width * rating / 100)
                    Color.gray
                        .frame(width: geo.size.width * (100 - rating) / 100)
                }
                .gesture(
                    DragGesture()
                        .onChanged({ value in
                            rating = ((value.translation.width + value.startLocation.x)
                                      / geo.size.width * 100.0)
                            rating = min(100, max(rating, 0))
                        })
                )
                .clipShape(RatingClipShape())
            }
            .frame(height: 80)
        }
        .padding(30)
    }
}


struct RatingClipShape: Shape {
    let paddingAmount = 5.0 // %
    func path(in rect: CGRect) -> Path {
        let padding = rect.width * paddingAmount / 100
        let diameter = (rect.width - (4 * padding)) / 5
        let step = diameter + padding
        var path = Path()
        for i in 0..<5 {
            path.addEllipse(in: CGRect(x: Double(i)*step, y: 0, width: diameter, height: diameter))
        }
        return path
    }
}

Result:
enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SwiftUI 拖动手势坐标 的相关文章

随机推荐