Joe Scotto
Joe Scotto

Reputation: 10867

Add modifier to all instances of view

I want to use my theme color on all instances of Toggle(), is there a way to do this with an extension?

extension Toggle {
    func content() -> some View {
        self.tint(.red)
    }
}

The above is not working, is there something else I should call on the extension to modify all instances of Toggle?

Upvotes: 1

Views: 485

Answers (3)

Rob Napier
Rob Napier

Reputation: 299345

This is exactly what .toggleStyle is designed for. Create your own custom ToggleStyle:

struct MyToggleStyle: ToggleStyle {
    func makeBody(configuration: Configuration) -> some View {
        // This just extends the default Toggle appearance, but you can return
        // any View you like here. It doesn't have to call `Toggle` first.
        Toggle(configuration)
            .tint(.red) // Along with whatever other styles you like
    }
}

extension ToggleStyle where Self == MyToggleStyle {
    static var myToggleStyle: MyToggleStyle { .init() }
}

Then in your top-level ContentView, add the modifier:

.toggleStyle(.myToggleStyle)

Your style will be applied to all Toggles inside of your ContentView.

Upvotes: 2

Kush Bhavsar
Kush Bhavsar

Reputation: 1037

If you want to create a modifier to apply to an instance of Toggle(), can do that with the help of ViewModifiers.

i.e: First create a ViewModifier:

struct TintColorModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .tint(.red)
    }
}

extension Toggle {
    func tintStyle() -> some View {
        modifier(TintColorModifier())
    }
}

Now you can use the extension this way:

struct ContentView: View {
    var body: some View {
        Toggle()
            .tintStyle() // <-- Here
    }
}

Upvotes: 0

Gavin Morrow
Gavin Morrow

Reputation: 769

The best way to do this is to make a custom view with @ViewBuilder.

struct CustomToggle<Content: View>: View {
    var isOn: Binding<Bool>
    var label: Content

    var body: some View {
        Toggle(isOn: isOn) { label }
            .tint(.red)
    }
    
    init(isOn: Binding<Bool>, @ViewBuilder label: @escaping () -> Content) {
        self.isOn = isOn
        self.label = label()
    }
}

Upvotes: 1

Related Questions