Swift

UIButtonのHighlightedをいい感じにするUIButtonサブクラス

環境

Xcode9.4

仕様

titleColor, borderColor, image, backgroundImage, backgroundColorに対応。

titleColor, borderColor, image, backgroundImageはちょい透明になります
backgroundColorはちょい白っぽくなります。

※Animationではなくパット切り替わります

使い方

以下のコードを適当なファイル名でPJに含める。
highlightedをいい感じにしたいUIButtonに継承させる。

backgroundColorに.clearを設定すると、highlighted時に白っぽくなります。(storyboardなどでdefaultだとnilなので白くなりません)

コード

@IBDesignable
extension UIView {
    // 枠線の色
    @IBInspectable var borderColor: UIColor? {
        get {
            return layer.borderColor.map { UIColor(cgColor: $0) }
        }
        set {
            layer.borderColor = newValue?.cgColor
        }
    }

    // 枠線のWidth
    @IBInspectable var borderWidth: CGFloat {
        get {
            return layer.borderWidth
        }
        set {
            layer.borderWidth = newValue
        }
    }
}

class HighlightButton: UIButton {

    // MARK: Parameter

    private var normalBorderColor: UIColor?
    private var highlightedBorderColor: UIColor?

    override var borderColor: UIColor? {
        didSet {
            self.normalBorderColor = self.borderColor
            self.highlightedBorderColor = self.borderColor?.withAlphaComponent(0.4)
        }
    }

    override var isHighlighted: Bool {
        didSet {
            if self.borderWidth > 0 {
                self.layer.borderColor = self.isHighlighted ? self.highlightedBorderColor?.cgColor : self.normalBorderColor?.cgColor
            }
        }
    }

    override var backgroundColor: UIColor? {
        get {
            return super.backgroundColor
        }
        set {
            super.backgroundColor = newValue
            self.setBackgroundImage(newValue?.image, for: .normal)
        }
    }

    // MARK: Init

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.commonInit()
    }

    func commonInit() {
        self.borderColor = super.borderColor

        if let image = self.image(for: .normal) {
            super.setImage(image.translucent(), for: .highlighted)
        }

        if let color = self.titleColor(for: .normal) {
            super.setTitleColor(color.withAlphaComponent(0.4), for: .highlighted)
        }

        if let color = self.backgroundColor {
            self.setBackgroundImage(color.image, for: .normal)
        } else if let image = self.backgroundImage(for: .normal) {
            super.setBackgroundImage(image.translucent(), for: .highlighted)
        }
    }

    // MARK: Func

    override func setImage(_ image: UIImage?, for state: UIControlState) {
        super.setImage(image, for: state)

        if let image = image, state == .normal {
            super.setImage(image.translucent(), for: .highlighted)
        }
    }

    override func setTitleColor(_ color: UIColor?, for state: UIControlState) {
        super.setTitleColor(color, for: state)

        if let color = color, state == .normal, self.titleColor(for: .highlighted) != nil {
            super.setTitleColor(color.withAlphaComponent(0.4), for: .highlighted)
        }
    }

    override func setBackgroundImage(_ image: UIImage?, for state: UIControlState) {
        super.setBackgroundImage(image, for: state)

        if let image = image, state == .normal, self.backgroundImage(for: .highlighted) != nil {
           super.setBackgroundImage(image.blend(UIColor.white.withAlphaComponent(0.6).image), for: .highlighted)
        }
    }
}