Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
202 views
in Technique[技术] by (71.8m points)

ios - How can create modifiers that are changing properties in a Custom View

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 ?

question from:https://stackoverflow.com/questions/66052728/how-can-create-modifiers-that-are-changing-properties-in-a-custom-view

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...