Home > Net >  How to make UIButton.Configuration highlight appearance match that of system buttons
How to make UIButton.Configuration highlight appearance match that of system buttons

Time:11-05

I'm modernizing my app and updating UIButtons to use UIButton.Configuration. I switched a system button to the default plain configuration style but was surprised to find the button highlight state is barely noticeable. When you tap down on a traditional system button, its alpha decreases a lot to indicate it’s being pressed, so it’s easy to know when you release the touch this button will be triggered. Unfortunately with the plain button configuration, the highlight state is hard to see because the appearance barely changes. Is there a way to make this highlight behave like all the other buttons such as UIBarButtonItems?

let oldButton = UIButton(type: .system)
oldButton.setTitle("System Button", for: .normal)
oldButton.frame = CGRect(x: 50, y: 100, width: 150, height: 30)
view.addSubview(oldButton)

let newButton = UIButton(configuration: {
    var config = UIButton.Configuration.plain()
    config.title = "Plain Button"
    return config
}())
newButton.frame = CGRect(x: 50, y: 150, width: 150, height: 30)
view.addSubview(newButton)

This is the highlight state of the system button:

enter image description here

This is the highlight state of the plain button:

enter image description here

CodePudding user response:

That's what a titleTextAttributesTransformer is for. With it, you can describe to the runtime what you want done in particular states of the button, such as when it is highlighted. Example:

let newButton = UIButton(configuration: {
    var config = UIButton.Configuration.plain()
    config.title = "Plain Button"
    return config
}())
newButton.configuration?.titleTextAttributesTransformer = .init { 
    [unowned newButton] container in
    var newContainer = AttributeContainer()
    guard let baseColor = container.uiKit.foregroundColor else {
        return newContainer
    }
    switch newButton.state {
    case .highlighted:
        newContainer.foregroundColor = baseColor.withAlphaComponent(0.3)
    default:
        newContainer.foregroundColor = baseColor
    }
    return container.merging(newContainer)
}

Feel free to tweak the "magic number" 0.3 to suit your taste.

(This may seem like a lot of work, but you only have to do it once if you define a base button and derive all your app's other buttons from it. In our app, we have defined an entire cascade of button styles deriving from the base.)

  • Related