Reputation: 3749
I have this CircularProgressView written in SwiftUI. I want to create a way to add some custom modifiers so I can change some properties from the parent view. The bellow code is not working.
I am talking about func lineWidth(width:CGFloat) -> some View , func progressBarColor(color:Binding) -> some View { , func tintColor(color:Color) -> some View {
struct CircularProgressView: View {
@Binding var progress: CGFloat
@State private var lineWidth:CGFloat = 15
@State private var progressBarColor:Color = Color.red
@State private var tintColor:Color = Color.gray
func lineWidth(width:CGFloat) -> some View {
self.lineWidth = width
return self
}
func progressBarColor(color:Color) -> some View {
self.progressBarColor = color
return self
}
func tintColor(color:Color) -> some View {
self.tintColor = color
return self
}
var body: some View {
GeometryReader { geometry in
ZStack {
Circle()
.stroke(tintColor, lineWidth: lineWidth)
.aspectRatio(1, contentMode: .fit)
Circle()
.trim(from: 0.0, to: progress)
.stroke(progressBarColor, lineWidth: lineWidth)
.rotationEffect(Angle(degrees: -90))
.aspectRatio(1, contentMode: .fit)
}
}
}
}
For example. I want to use this CircularProgressView like this:
struct ContentView: View {
var body: some View {
CircularProgressView(progress: .constant(0.3)).lineWidth(width: 20)
}
}
How can achieve this with ViewModifiers?. Am I thinking this all wrong ?
Upvotes: 3
Views: 1160
Reputation: 257663
You just don't need @State
wrapper for all those properties, so use just as
struct CircularProgressView: View {
@Binding var progress: CGFloat
private var lineWidth:CGFloat = 15
private var progressBarColor:Color = Color.red
private var tintColor:Color = Color.gray
// ... other code
func lineWidth(width:CGFloat) -> some View { // << here !!
var newView = self
newView.lineWidth = width
return newView
}
}
but @Binding
should remain as-is because it is like a reference to external source of truth (some dynamic property holding real value), binding itself does not do anything - it is just like a proxy.
So the following is useless
func progressBarColor(color:Binding<Color>) -> some View {
self.progressBarColor = color.wrappedValue
return self
}
you should use it like
struct ContentView: View {
@State private var progress = 0.3
var body: some View {
CircularProgressView(progress: $progress).lineWidth(width: 20)
// ... modify progress somewhere later
}
}
*** however I don't see in the provided scenario why would you need binding at all... if you'd remove it from CircularProgressView
, then the following would also work
struct ContentView: View {
@State private var progress = 0.3
var body: some View {
CircularProgressView(progress: progress).lineWidth(width: 20)
// ... modify progress somewhere later
}
}
Upvotes: 2