I'm trying to add a rating system to an application I'm writing. My approach is less than elegant by using a Stepper. I'd like an interactive way of dragging to fill the star rating if possible.
I'm not sure if DragGesture is what I'm looking for, would this suffice? Also, I'm unsure how I would convert the coordinates to the proper width to fill the stars. Any help would be appreciated.
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")
}
})
}
}
}

