skip to Main Content

I use custom ButtonStyle to change colour of button in pressed state

Button(action: action) {
    bodyView
}
.buttonStyle(ListCellButtonStyle())

private struct ListCellButtonStyle: ButtonStyle {

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .overlay(
                Rectangle()
                    .foregroundColor(configuration.isPressed ? .statePressed : .clear)
            )
    }
}

But this remove default behaviour of showing Button shapes in accessibility mode:

Settings > Accessibility > Display & Text Size -> Button Shapes -> true

How can I get the code of DefaultButtonStyle to copy this related staff, or how can I not create a new ButtonStyle, but modify DefaultButtonStyle?

2

Answers


  1. When you’re creating your own button styles, you can use accessibility environment variables to make your style respond to user changes.

    For the button shapes setting, the environment property is .accessibilityShowButtonShapes, so you could monitor that value and adjust your style accordingly. For example, if you had a shape whose background you wanted to be visible when button shapes need to be shown, you could use the variable to adjust its opacity:

    private struct ListCellButtonStyle: ButtonStyle {
        @Environment(.accessibilityShowButtonShapes) private var accessibilityShowButtonShapes
    
        func makeBody(configuration: Configuration) -> some View {
           // some view
           .background {
             Color.gray.opacity(accessibilityShowButtonShapes ? 0.2 : 0.0)
           }
        }
    }
    
    Login or Signup to reply.
  2. You could use a dummy button with default styling as the base view and apply your custom button as an overlay. When button shapes is turned on, the button shape is seen behind your styling in the foreground.

    By making the dummy button the base view, rather than showing it as a background layer, the extra padding that is added when button shapes is turned on takes effect for the whole shape. So there is no need to add any padding yourself.

    func makeBody(configuration: Configuration) -> some View {
        Button {} label: { configuration.label.hidden() }
            .disabled(true)
            .overlay {
                configuration.label
            }
            .overlay {
                if configuration.isPressed {
                    Color.statePressed
                }
            }
    }
    

    You will notice that the label of the dummy button is hidden. This prevents it from being seen, but it still occupies the same space in the layout. So when button shapes is turned on, the shape has the right size for your label in the foreground. Also, the overlay for when the button is pressed is applied to the base view, so that it also adopts the size of the base view.

    Buttons

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search