How do I change the color of an SF Symbols based UIButton embedded in a UIAction?

836 Views Asked by At

I'm generating a button with the following code but am unable to successfully change the button's foreground color.

let button = UIButton(
    type: .close,
    primaryAction: UIAction(
        image: UIImage(systemName: "x.circle"),
        handler: { _ in }
    )
)

I've tried

  • UIImage(systemName: "x.circle")?.withTintColor(.red)

  • UIImage(systemName: "x.circle")?.withTintColor(.systemRed, renderingMode: .alwaysOriginal)

  • button.setTitleColor(.systemRed, for: .normal)

  • Adding a configuration:

    var config = UIButton.Configuration.borderless()
    config.baseForegroundColor = .systemRed
    button.configuration = config
    
  • Using a different symbol variant like: UIImage(systemName: "x.circle.fill")

In this specific scenario I want to change the color of the circular background area of the image only and not the X (crosses) or the button's background. Essentially I want a red filled circle with a gray X (crosses).

So I can get this: enter image description here

But I want something more like this (with the red limited to inside the circle): enter image description here

2

There are 2 best solutions below

0
On BEST ANSWER
  1. Change type from .close to .custom

  2. Change UIImage(systemName: "x.circle") to

    UIImage(systemName: "x.circle")?.withTintColor(.systemRed, renderingMode: .alwaysOriginal)

0
On

Both of these work:

or

yourButton.showsMenuAsPrimaryAction = true
var elements: [UIMenuElement] = yourData.map({ item in
    
    let conf = UIImage.SymbolConfiguration(
                  paletteColors: [item.color]
               ).applying(UIImage.SymbolConfiguration(
                  pointSize: 40,
                  weight: .heavy)
               )
    
    let acn = UIAction(
        title: item.name,
        image: UIImage(
               systemName: "map",
               withConfiguration: conf)
    ) { [weak self] _ in
        guard let self else { return }
        yourButtonProcess(item.code)
    }
    return acn
})
yourButton.menu = UIMenu(children: elements)

In the "palette", for some symbols use more than one color. You'll soon get the idea.

or

yourButton.showsMenuAsPrimaryAction = true
var elements: [UIMenuElement] = yourData.map({ item in
    
    let acn = UIAction(
        title: item.name,
        image: UIImage(
            systemName: "map")?
            .withTintColor(
               item.color,
               renderingMode: .alwaysOriginal) // don't forget
    ) { [weak self] _ in
        guard let self else { return }
        yourButtonProcess(item.code)
    }
    return acn
})
yourButton.menu = UIMenu(children: elements)

There you go.