Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I know if a SwiftUI Button is enabled/disabled?

Tags:

swift

swiftui

There is no isEnabled property for a SwiftUI button. How can i tell if it is enabled?

In regular UIKit, i would simply do

if button.isEnabeld == true {
} else {
}

but there is no SwiftUI equivalent.

like image 720
Just a coder Avatar asked Jul 02 '19 09:07

Just a coder


2 Answers

Inside a view, if you wish to react to the state set by .disabled(true), you can use: @Environment(\.isEnabled) var isEnabled

Since the environment can be used from within a View or a ViewModifier, this can be used to change layout properties of a view based on the state set from outside.

Unfortunately, ButtonStyle cannot directly use @Environment, but you can use a ViewModifier to inject environment values into a ButtonStyle in order to use the value from within a ButtonStyle:


// First create a button style that gets the isEnabled value injected
struct MyButtonStyle: ButtonStyle {
    private let isEnabled: Bool
    init(isEnabled: Bool = true) {
        self.isEnabled = isEnabled
    }
    func makeBody(configuration: Configuration) -> some View {
        return configuration
            .label
            .background(isEnabled ? .green : .gray)
            .foregroundColor(isEnabled ? .black : .white)
    }
}

// Then make a ViewModifier to inject the state
struct MyButtonModifier: ViewModifier {
    @Environment(\.isEnabled) var isEnabled
    func body(content: Content) -> some View {
        return content.buttonStyle(MyButtonStyle(isEnabled: isEnabled))
    }
}

// Then create a convenience function to apply the modifier
extension Button {
    func styled() -> some View {
        ModifiedContent(content: self, modifier: MyButtonModifier())
    }
}

// Finally, try out the button and watch it respond to it's state
struct ContentView: View {
    var body: some View {
        Button("Test", {}).styled().disabled(true)
    }
}

You can use this method to inject other things into a ButtonStyle, like size category and theme.

I use it with a custom style enum that contains all the flavours of button styles found in our design system.

like image 100
Morten Bek Ditlevsen Avatar answered Sep 20 '22 11:09

Morten Bek Ditlevsen


From outside a view you should know if you used .disabled(true) modifier.

From inside a view you can use @Environment(\.isEnabled) to get that information:

struct MyButton: View {
    let action: () -> Void
    @Environment(\.isEnabled) private var isEnabled

    var body: some View {
        Button(action: action) {
            Text("Click")
        }
        .foregroundColor(isEnabled ? .green : .gray)
    }
}

struct MyButton_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            MyButton(action: {})
            MyButton(action: {}).disabled(true)
        }
    }
}
like image 23
Łukasz Gierałtowski Avatar answered Sep 18 '22 11:09

Łukasz Gierałtowski