我有一个带有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
子类添加到另一个视图中,并使用自动布局来设置其宽度。它以 awakeFromNib()
为单位返回的宽度只是它在 xib 中的值。如何获取轨道的实际自动布局宽度来解决此问题?
使路径独立于位置
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
}