I want to create a UI like this in SwiftUI. I tried using path and geometryReader but I can't find the proper solution.
CodePudding user response:
Maybe something like this?
struct ProbabilityView: View {
var title: String
var value: Double
var body: some View {
VStack(alignment: .leading) {
Text(title)
GeometryReader { proxy in
ZStack(alignment: .leading) {
HStack(spacing: 0) {
Color.green
Color.yellow
Color.red
}
.cornerRadius(8)
.frame(maxHeight: 16)
Text(formatted)
.font(.callout)
.padding(.vertical, 3)
.frame(width: 52)
.background(Color(.systemBackground))
.cornerRadius(16)
.shadow(radius: 8)
// Substract the width of the bubble
.offset(x: (proxy.size.width - 52) * value)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
.animation(.default, value: value)
}
.padding(.bottom, 10)
}
var formatted: String {
let value = self.value * 100
return "\(Int(value.rounded())) %"
}
}
Demo
struct ContentView: View {
@State private var value = 0.0
var body: some View {
List {
Section {
ProbabilityView(title: "Virus probability score", value: value)
}
Section {
Button {
value = 0
} label: {
Text("0%")
}
Button {
value = 0.5
} label: {
Text("50%")
}
Button {
value = 1.0
} label: {
Text("100%")
}
Button {
value = Double.random(in: 0...1)
} label: {
Text("Random")
}
}
}
.listStyle(.grouped)
}
}
CodePudding user response:
Here’s a Shape
to round custom corners:
struct RoundedRectangleEdge: Shape {
var corners: UIRectCorner
var radius: CGFloat
func path(in rect: CGRect) -> Path {
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
return Path(path.cgPath)
}
}
You can use an HStack
& a combination of the above shape to create the ProgressBar. Make sure to set the spacing to 0.