相对于 UIButton 框架的 drawRect 框架不正确

Incorrect drawRect frame relative to UIButton frame

我正在尝试向某些 UIButton 添加状态指示器,将其直接插入以下屏幕截图中蓝色指示器所在的位置。我首先通过使用 minY 和 minX 从头开始​​创建第一行指标代码来使用 UIButton 原点作为参考点来进行校准,然后将其复制到其他两个指标,认为它应该翻译,但似乎没有。

//In header/property declaration
    @IBOutlet weak var thirdButton: UIButton!
    @IBOutlet weak var secondButton: UIButton!
    @IBOutlet weak var firstButton: UIButton!

    var capicheIndicator: UIView!
    var secondIndicator: UIView!
    var thirdIndicator: UIView!

// In viewDidLoad
        let firstButtonFrame = firstButton.frame
        self.capicheIndicator = DrawBlueCircle(frame: CGRect(x: firstButtonFrame.minX + 15, y: firstButtonFrame.minY + 4, width: 11, height: 11))
        self.view.addSubview(capicheIndicator)

        let secondButtonFrame = secondButton.frame
        self.secondIndicator = DrawYellowCircle(frame: CGRect(x: secondButtonFrame.minX + 15, y: secondButtonFrame.minY + 4, width: 11, height: 11))
        self.view.addSubview(secondIndicator)

        let thirdButtonFrame = thirdButton.frame
        self.thirdIndicator = DrawRedCircle(frame: CGRect(x: thirdButtonFrame.minX + 15, y: thirdButtonFrame.minY + 4, width: 11, height: 11))
        self.view.addSubview(thirdIndicator).

这是我绘制每个指标的方式,圆圈颜色填充代码行是 DrawBlueCircle、DrawYellowCircle 和 DrawRedCircle 之间的唯一变化。

class DrawBlueCircle: UIView {

    override func drawRect(rect: CGRect)
    {
        let contextRef = UIGraphicsGetCurrentContext()

        CGContextClearRect(contextRef, rect)

        //Set the border width
        CGContextSetLineWidth(contextRef, 1.5)

        //Set the circle fil
        CGContextSetRGBFillColor(contextRef, 0/255, 122/255, 1, 1)

        CGContextFillEllipseInRect(contextRef, rect)
    }
}

然而不幸的是,只有蓝色指示器被正确绘制。

在我尝试调试的过程中,我将每一步都打印到控制台,如下面的代码所示,但是代码和屏幕不匹配。

 let firstButtonFrame = firstButton.frame
    print(firstButtonFrame)
    print(firstButtonFrame.minY)
    self.capicheIndicator = DrawBlueCircle(frame: CGRect(x: firstButtonFrame.minX + 15, y: firstButtonFrame.minY + 4, width: 11, height: 11))
    print(capicheIndicator.frame)
    self.view.addSubview(capicheIndicator)

    let secondButtonFrame = secondButton.frame
    print(secondButtonFrame)
    print(secondButtonFrame.minY)
    self.secondIndicator = DrawYellowCircle(frame: CGRect(x: secondButtonFrame.minX + 15, y: secondButtonFrame.minY + 4, width: 11, height: 11))
    print(secondIndicator.frame)
    self.view.addSubview(secondIndicator)

    let thirdButtonFrame = thirdButton.frame
    print(thirdButtonFrame)
    print(thirdButtonFrame.minY)
    self.thirdIndicator = DrawRedCircle(frame: CGRect(x: thirdButtonFrame.minX + 15, y: thirdButtonFrame.minY + 4, width: 11, height: 11))
    print(thirdIndicator.frame)
    self.view.addSubview(thirdIndicator)

控制台输出:

(36.0, 381.0, 528.0, 40.0)
381.0
(51.0, 385.0, 11.0, 11.0)
(36.0, 431.0, 528.0, 40.0)
431.0
(51.0, 435.0, 11.0, 11.0)
(36.0, 481.0, 528.0, 40.0)
481.0
(51.0, 485.0, 11.0, 11.0)

通过继承 UIView 并添加一个按钮,可以更轻松地完成此操作。只需将指标添加为子视图即可。在 Playground 试试这个:

class IndicatorButton: UIView {

    let indicatorView: UIView = {
        let indicator = UIView(frame: CGRectMake(0,0,10,10))
        indicator.layer.cornerRadius = 5.0
        indicator.clipsToBounds = true
        indicator.backgroundColor = UIColor.clearColor()
        return indicator
    }()

    var indicatorColor: UIColor = UIColor.clearColor() {
        didSet {
            indicatorView.backgroundColor = indicatorColor
            self.layer.borderColor = indicatorColor.CGColor
            self.button.setTitleColor(indicatorColor, forState: .Normal)
        }
    }

    let button: UIButton = {
        let button = UIButton(type: .Custom)
        return button
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.layer.borderWidth = 2.0
        self.layer.borderColor = indicatorColor.CGColor
        self.layer.cornerRadius = 8.0
        self.clipsToBounds = true
        button.frame = CGRectMake(0, 0, frame.size.width, frame.size.height)
        button.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
        button.titleEdgeInsets = UIEdgeInsetsMake(0,15,0,0)
        self.addSubview(button)
        self.addSubview(indicatorView)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    override func layoutSubviews() {
        super.layoutSubviews()
        indicatorView.frame = CGRectMake(10, (self.bounds.size.height-10) / 2.0, 10,10)
    }

}

像这样使用它:

let b = IndicatorButton(frame: CGRectMake(0,0,100,30))
b.indicatorColor = UIColor.redColor()
b.button.setTitle("Start", forState: .Normal)
b

结果: