自定义滑块和自动布局问题

时间:2017-02-08 13:42:14

标签: ios swift

我有一个带有xib的UIView子类,我正试图将其放入一个带有离散点的滑块上。

我有一个“轨道”和一个“拇指”。沿着轨道,我想要有4个均匀间隔的圆圈,拇指可以在拖动时捕捉到它。

我正在使用的代码如下:

override func awakeFromNib() {
    // Layout circles
    for index in stride(from: numberOfCircles, to: 0, by: -1) {
        let xValue = (((index - 1)/(numberOfCircles - 1))*track.frame.size.width) - circleSize/2 + thumbWidth.constant/2
        makeCircle(withXValue: xValue)
    }
}

fileprivate func makeCircle(withXValue xValue: CGFloat) {
    let circle = CAShapeLayer()
    circle.path = UIBezierPath(ovalIn: CGRect(x: xValue , y: self.frame.height/2 - circleSize/2, width: circleSize, height: circleSize)).cgPath
    circle.fillColor = UIColor(red: 238/255, green: 79/255, blue: 84/255, alpha: 1).cgColor
    self.layer.addSublayer(circle)
}

我认为这会奏效,但track.frame.size.width不正确。这是因为我将这个UIView子类添加到另一个视图并使用autolayout来设置其宽度。它在awakeFromNib()中返回的宽度就是它在xib中的值。 如何获取轨道的实际自动布局宽度以解决此问题?

1 个答案:

答案 0 :(得分:0)

使路径独立于位置

circle.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: circleSize, height: circleSize)).cgPath

而不是使用position类的CALayer属性:

circle.position = CGPoint(x: xValue , y: self.frame.height/2 - circleSize/2)

将圆圈图层保存在属性中,以便在框架更改时可以访问它们。让你的图层的创建方法返回它创建的图层makeCircle(withXValue xValue: CGFloat) -> CAShapeLayer。并将其保存在awakeFromNib()circles.append(makeCircle(withXValue: calculateXValueForCircle(atIndex: index))

当您的视图框架发生变化时,将调用方法layoutSublayers。覆盖方法layoutSublayers(of layer: CALayer)以使用新帧值设置位置:

    override func layoutSublayers(of layer: CALayer) {
        super.layoutSublayers(of: layer)
        if layer == self.layer {
            for (index, circle) in circles.enumerated() {
                let newX = calculatePositionForCircle(atIndex: index)
                let newY = self.frame.height/2 - circleSize/2
                circle.position = CGPoint(x: newX, y: newY)
            }
        }
    }

    // Calculating X position better move in method so you don't dublicate your code
    fileprivate func calculatePositionForCircle(atIndex index: Int) -> CGFloat {
        return (((index - 1)/(numberOfCircles - 1))*track.frame.size.width) - circleSize/2 + thumbWidth.constant/2
    }