UIButtonのアイコンのダークモード対応


背景

ダークモード対応を行う際、単純にボタンのTextColorだけを変えるとこうなります🤯

デザイナーさんも忙しそうだし、ボタンに設定してる単色アイコンくらいならコードで色を変えた方が楽なのでは…?
ということで、UIButtonのカスタムクラスを作成することにしました。

やってみる

こちらが今回作ったものです。
ボタンのアイコンとテキストを別な色で設定したい人向けです。

カスタムクラスを用意する

まず@IBInspectableでStoryboardから色を設定できるようにします。
そして画面を表示している途中でモードを切り替えた時のためにdraw()の中で色を変更します。
ついでにハイライトの色もセットしておきます。


class IconButton: UIButton {
    @IBInspectable var iconColor: UIColor?

    override func draw(_ rect: CGRect) {
        super.draw(rect)
        self.setTitleColor(self.currentTitleColor.withAlphaComponent(0.5), for: .highlighted)

        if let image = self.image(for: .normal), let iconColor = self.iconColor {
            self.setImage(image.tint(color: iconColor), for: .normal)
            self.setImage(image.tint(color: iconColor.withAlphaComponent(0.5)), for: .highlighted)
        }
    }
}

extension UIImage {
    func tint(color: UIColor) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.size, false, 0)
        color.setFill()
        let drawRect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
        UIRectFill(drawRect)
        self.draw(in: drawRect, blendMode: .destinationIn, alpha: 1)
        let tintedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return tintedImage
    }
}

Storyboardで設定する

ボタンのCustomClassに先ほど作成したクラスを設定します。

iconColorに画像の色(ダークモード対応済みのもの)を設定します。

できました

ライトモード

ダークモード

ハイライトはそれぞれこんな感じ

完成👏

本当は…

SF Symbolsを使えばサクッとダークモード対応ができるみたいなので、もし可能であればそちらを使った方が良いかもしれません。
https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/