美文网首页iOS 杂谈iOS
怎样给 UIButton 的 status 绑定 backGro

怎样给 UIButton 的 status 绑定 backGro

作者: 深度码农患者 | 来源:发表于2018-05-14 11:41 被阅读3次

在开发中,经常能碰到需要给不同status设置不同的 backgroundColor 或者 borderColor ,如果新建一个子类的话可能会很麻烦,这时候,如果用 extension 仿照 setTitleColor 的方法新写一个 setBackGroundColor 的方法封装一下就感觉很惬意了,话不多说,上代码:
先设置对外接口

   open func setBackgroudColor(_ color: UIColor, for state: UIControlState) {
        backGroundColorsForStates[state.rawValue] = color
        onStateChanged()
    }

    open func setBoarderColor(_ color: UIColor, for state: UIControlState) {
        boarderColorsForStates[state.rawValue] = color
        onStateChanged()
    }

这时候出现了 boarderColorsForStates 属性和 onStateChanged 方法,status 绑定的 backGroundColor 需要存储到某个属性中,而 extension 是无法添加属性的,此时我们只好用简单的运行时方法,给 UIButton 添加一个简单的键值对属性,即

private var boarderColorsForStates: [UInt: UIColor] {
        get {
            return (objc_getAssociatedObject(self, &UIButtonObjectKeys.boarderColorsForStates) as? [UInt: UIColor]) ?? [UInt: UIColor]()
        }
        set {
            objc_setAssociatedObject(self, &UIButtonObjectKeys.boarderColorsForStates, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }
  
    private var backGroundColorsForStates: [UInt: UIColor] {
        get {
            return (objc_getAssociatedObject(self, &UIButtonObjectKeys.backGroundColorsForStates) as? [UInt: UIColor]) ?? [UInt: UIColor]()
        }
        set {
            objc_setAssociatedObject(self, &UIButtonObjectKeys.backGroundColorsForStates, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }

swift 中动态添加属性的 key 需要时 UnsafeRawPointer 格式的,UnsafeRawPointer 格式也就是类似于 OC 中的指针,即取 String 的指针作为 key 传过去。
而 onStateChanged() 是在 UIButton status 状态改变时传作一些操作,例如设置 status 对应的 backGroundColor,即:

 private func onStateChanged() {
        if let color = self.backGroundColorsForStates[self.state.rawValue] {
            self.backgroundColor = color
        } else if let color = self.backGroundColorsForStates[UIControlState.normal.rawValue] {
            self.backgroundColor = color
        }
        
        if let color = self.boarderColorsForStates[self.state.rawValue] {
            self.borderColor = color
        } else if let color = self.boarderColorsForStates[UIControlState.normal.rawValue] {
            self.borderColor = color
        }
    }

同样的,在设置 selected、highlighted、enabled 时也要调用这个方法,即重写这三个值的 set 方法和 get 方法:

override open var isSelected: Bool {
        get {
            return super.isSelected
        }
        set {
            if newValue != isSelected {
                super.isSelected = newValue
                onStateChanged()
            }
        }
    }
    
    override open var isHighlighted: Bool {
        get {
            return super.isHighlighted
        }
        set {
            super.isHighlighted = newValue
            onStateChanged()
        }
    }
    
    override open var isEnabled: Bool {
        get {
            return super.isEnabled
        }
        set {
            if newValue != isSelected {
                super.isEnabled = newValue
                onStateChanged()
            }
        }
    }

到这里,添加的这个 extension 就算大功告成了,你可以尝试给 UIButton 设置不同 status 下的 backGroundColor 等属性

相关文章

网友评论

    本文标题:怎样给 UIButton 的 status 绑定 backGro

    本文链接:https://www.haomeiwen.com/subject/qypddftx.html