【问题标题】:Custom UIButton isSelected background color not working as expected (IOS / Swift)自定义 UIButton isSelected 背景颜色未按预期工作(IOS / Swift)
【发布时间】:2018-04-10 04:33:00
【问题描述】:

我有一个自定义的 UIButton 类,其中此代码无法按预期工作:

    override var isSelected: Bool {
        didSet {
            backgroundColor = isSelected ? UIColor.blue : UIColor.white
        }
    }

当我在代码中设置isSelected 时,背景不会改变......它保持白色。不过,我知道实际的布尔值 isSelected true/false 实际上是正确切换的。

didSet 中的代码正在执行(我已通过打印调试验证),但不知何故没有设置背景。

有趣的是,我还以完全相同的方式覆盖了isHighlighted 方法,效果很好。

这是自定义按钮类的完整代码。 随意将其剪切/粘贴到您的 XCODE 中并使用它

import UIKit

@IBDesignable
class PlusMinusButton: UIButton {

    @IBInspectable
    var highlightColor: UIColor = .yellow { didSet { setNeedsDisplay() } }

    @IBInspectable
    var fillColor: UIColor = .yellow { didSet { setNeedsDisplay() } }

    @IBInspectable
    var strokeColor: UIColor = .yellow { didSet { setNeedsDisplay() } }

    @IBInspectable
    var plusOrMinus: Bool = true { didSet { setNeedsDisplay() } }


    func getPath() -> UIBezierPath {

        let G = bounds.width / 5

        let path = UIBezierPath()

        switch plusOrMinus {

        case true:

            let startPoint = CGPoint(x:2*G,y:G)
            path.move(to: startPoint)
            path.addLine(to: CGPoint(x:2*G,y:2*G))
            path.addLine(to: CGPoint(x:G,y:2*G))
            path.addLine(to: CGPoint(x:G,y:3*G))
            path.addLine(to: CGPoint(x:2*G,y:3*G))
            path.addLine(to: CGPoint(x:2*G,y:4*G))
            path.addLine(to: CGPoint(x:3*G,y:4*G))
            path.addLine(to: CGPoint(x:3*G,y:3*G))
            path.addLine(to: CGPoint(x:4*G,y:3*G))
            path.addLine(to: CGPoint(x:4*G,y:2*G))
            path.addLine(to: CGPoint(x:3*G,y:2*G))
            path.addLine(to: CGPoint(x:3*G,y:G))
            path.addLine(to: startPoint)

        case false:

            let startPoint = CGPoint(x:G,y:3*G)

            path.move(to: startPoint)
            path.addLine(to: CGPoint(x:4*G,y:3*G))
            path.addLine(to: CGPoint(x:4*G,y:2*G))
            path.addLine(to: CGPoint(x:G,y:2*G))
            path.addLine(to: startPoint)

        }

        path.close()

        return path

    }

    // see how is method is exactly the same as the next?  weird, huh?
    override var isHighlighted: Bool {
        didSet {
            backgroundColor = isHighlighted ? highlightColor : UIColor.white
        }
    }

    override var isSelected: Bool {
        didSet {
            print("This line of code is executed!!")
            backgroundColor = isSelected ? UIColor.blue : UIColor.white
        }
    }

    override func draw(_ rect: CGRect) {

        let path = getPath()

        fillColor.setFill()

        path.fill()

        strokeColor.setStroke()

        path.stroke()

    }
}

感谢您的帮助!我敢打赌这真的很愚蠢!默普! :B

【问题讨论】:

  • 提供您选择的设置代码。就像在您的视图或控制器中一样
  • 感谢您抽出宝贵时间,但这不是必需的,因为“我知道实际的布尔值 .isSelected true/false 实际上是正确切换的。didSet 中的代码正在执行(我已通过打印调试验证),但不知何故没有设置背景。”
  • 可以尝试在 willSet 方法中设置背景颜色吗?

标签: ios swift background uibutton


【解决方案1】:

阅读isSelectedisHighlightedsetNeedsDisplay()的文档后,我的理解是,在切换突出显示的值后,它会自动调用UIControl的更新/重绘过程。对于 isSelected 切换,这不能保证所有控件。我认为 UIButton 就是其中之一。

更新的解决方案: 我错过的一件事是,每当您点击按钮时 isHighlighted 的值更改为 true,而当点击结束时又更改回 false。因此,在您的情况下,只要点击结束,它就会变回backgroundcolor = UIColor.white。对于修复,我优先考虑 highLighted bool,然后是 isSelected bool 以设置背景颜色。请检查以下代码

override var isHighlighted: Bool {
        didSet {
            backgroundColor =  isHighlighted ? highlightColor : (isSelected ? UIColor.blue : UIColor.white)
        }
    }

override var isSelected: Bool {
        didSet {
            backgroundColor = isSelected ? UIColor.blue : UIColor.white
            setNeedsDisplay()
        }
    }

无效:

    override var isSelected: Bool {
        didSet {
            backgroundColor = isSelected ? UIColor.blue : UIColor.white
            setNeedsDisplay()
        }
    }

【讨论】:

  • 再次感谢您的努力。似乎不起作用。当然,这最终是我的错。 :)
  • 如果你喜欢,你可以把这个类直接剪切粘贴到你的 Xcode 中。
  • 可能发现了您的问题。现在正在开会。将在 30 分钟后再次发布
  • 你是冠军。解开谜团...谢谢!
  • PS - 您标记为“无效”的部分实际上仍然相同。此外,'setNeedsDisplay()' 不是必需的。
【解决方案2】:

您将在运行时更新一个 ui 组件。我认为你需要在运行时在主线程上执行代码。试试这个:

override var isSelected: Bool {

    didSet {

        print("This line of code is executed!!")

        DispatchQueue.main.async {

            self.backgroundColor = self.isSelected ? UIColor.blue : UIColor.white
        }
    }
}

override func draw(_ rect: CGRect) {

    self.tintColor = .clear

    let path = getPath()

    fillColor.setFill()

    path.fill()

    strokeColor.setStroke()

    path.stroke()

}

不要忘记将 tintColor 设置为清除,否则您会在按钮上看到一个蓝色方形圆点。

工作...!使用 Swift 4.0.2 在 Xcode 9.3 上测试代码

【讨论】:

    【解决方案3】:
    override func draw(_ rect: CGRect) {
    
        let path = getPath()
    
        fillColor.setFill()
    
        path.fill()
    
        strokeColor.setStroke()
    
        path.stroke()
    
      //ADD below line 
    
       self.backgroundColor = backgroundColor
    }
    

    【讨论】:

    • 谢谢你...试过但没有用。我理解为什么这可能会起作用的概念,但这就是为什么我包含这样的声明,“有趣的是,我还以完全相同的方式覆盖了 isHighlighted 方法,它工作正常。”
    • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值
    猜你喜欢
    • 2012-04-01
    • 2021-03-17
    • 2023-03-26
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    • 2011-11-11
    • 1970-01-01
    • 2018-06-29
    相关资源
    最近更新 更多