'How can I add my custom ButtonStyle to the shortcut swiftui .buttonstyle() property in swiftui3

In swiftui3 you can use buttonstyle shortcut like so


Button("0") {print("pressed 0")}
    .buttonStyle(.bordered)

I would like to do that with my custom buttonstyle class

struct CrazyButtonStyle:ButtonStyle{
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .foregroundColor(.red)
    }
}

calling it like this

Button("0") {print("pressed 0")}
    .buttonStyle(.crazy)

I have tried

extension ButtonStyle{
    static var crazy:CrazyButtonStyle {
        get {
            return CrazyButtonStyle()
        }
    }
}

but im getting this error

Contextual member reference to static property 'crazy' requires 'Self' constraint in the protocol extension


Solution 1:[1]

extension ButtonStyle where Self == CrazyButtonStyle{
    static var crazy:CrazyButtonStyle {
        get {
            return CrazyButtonStyle()
        }
    }
}

adding where Self to the extension seems to work. But im not sure if this is the best way.

Solution 2:[2]

You can define something like the following:

struct CrazyButtonStyle: ButtonStyle {
  func makeBody(configuration: Configuration) -> some View {
    HStack {
      Spacer()
      configuration.label.foregroundColor(.red)
      Spacer()
    }
    .scaleEffect(configuration.isPressed ? 0.90 : 1)
  }
}

Then, to apply it to a Button:

Button("Crazy Button") {}
  .buttonStyle(CrazyButtonStyle())

See swift docs for reference.

Also here are some other examples, with animations as well!

Solution 3:[3]

/// define your style
public struct MainButtonStyle: ButtonStyle {
    public init(){}
    public func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .frame(height: 50, alignment: .center)
            .frame(maxWidth: .infinity)
            .background(Color(.primary).clipShape(RoundedRectangle(cornerRadius: 4)))
            .foregroundColor(Color.white)
            .scaleEffect(configuration.isPressed ? 0.95: 1)
    }
}

/// create an enum of all new types you've just created
public enum ButtonStyles {
    case main
}

/// add a new functionality to the view
public extension View {

    @ViewBuilder
    func buttonStyle(_ style: ButtonStyles) -> some View {
        switch style {
        case .main:
            self.buttonStyle(MainButtonStyle())
        }
    }

}

then you can use it like this

Button { someAction() } label: {Text("COPY")}
  .buttonStyle(.main)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nic Wanavit
Solution 2 andrewlaguna824
Solution 3 Farshad jahanmanesh