我正在尝试创建2个层,它们相互堆叠并且位于自定义视图类的内部。
图层的图纸效果很好,但我只是无法让他们根据视图的位置来调整其位置,该视图是使用自动布局设置的,其中视图是在代码中创建的(无IB)。
我已经尝试通过调用layoutSubviews
来更改图层的框架,这是尝试的代码。
import UIKit
class ProgressView: UIView {
let displayLayer: CAShapeLayer = {
let display = CAShapeLayer()
display.strokeColor = UIColor.red.cgColor
display.lineWidth = 8.0
display.lineCap = CAShapeLayerLineCap.round
display.fillColor = UIColor.clear.cgColor
display.strokeEnd = 0.5
return display
}()
let trackLayer: CAShapeLayer = {
let track = CAShapeLayer()
track.strokeColor = UIColor.lightGray.cgColor
track.lineWidth = 6.0
track.lineCap = CAShapeLayerLineCap.round
track.fillColor = UIColor.clear.cgColor
return track
}()
override init(frame: CGRect) {
super.init(frame: frame)
let progressCircle = UIBezierPath(arcCenter: .zero, radius: 50, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
displayLayer.path = progressCircle.cgPath
trackLayer.path = progressCircle.cgPath
layer.addSublayer(trackLayer)
layer.addSublayer(displayLayer)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
displayLayer.frame = bounds
trackLayer.frame = bounds
}
}
经过研究,我还尝试了KVO方法,并使用了以下代码:
import UIKit
class ProgressView: UIView {
let displayLayer: CAShapeLayer = {
let display = CAShapeLayer()
display.strokeColor = UIColor.red.cgColor
display.lineWidth = 8.0
display.lineCap = CAShapeLayerLineCap.round
display.fillColor = UIColor.clear.cgColor
display.strokeEnd = 0.5
return display
}()
let trackLayer: CAShapeLayer = {
let track = CAShapeLayer()
track.strokeColor = UIColor.lightGray.cgColor
track.lineWidth = 6.0
track.lineCap = CAShapeLayerLineCap.round
track.fillColor = UIColor.clear.cgColor
return track
}()
override init(frame: CGRect) {
super.init(frame: frame)
let progressCircle = UIBezierPath(arcCenter: .zero, radius: 50, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
displayLayer.path = progressCircle.cgPath
trackLayer.path = progressCircle.cgPath
layer.addSublayer(trackLayer)
layer.addSublayer(displayLayer)
self.addObserver(self, forKeyPath: #keyPath(ProgressView.bounds), options: .new, context: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == #keyPath(ProgressView.bounds) {
displayLayer.frame = self.bounds
trackLayer.frame = self.bounds
}
}
}
在每个示例中,我都会得到相同的结果,并显示以下内容。请注意,紫色框是
ProgressView
,我希望这两层都在其中。我一直在看这个东西,以为有一些简单的事情我很想念或做错了,但是我看不到它。
我已经在
observeValue
和layoutSubviews
中都放入了print语句,以确保它们被调用并且可以正常工作。这是我所看到的:
提前致谢。
最佳答案
您需要提供以下正确的arcCenter
,而无需为frame
设置shapLayer
。
override func layoutSubviews() {
super.layoutSubviews()
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let progressCircle = UIBezierPath(arcCenter: center, radius: 50, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
displayLayer.path = progressCircle.cgPath
trackLayer.path = progressCircle.cgPath
}
结果
注意:我使用了第一个
ProgressView
类,而没有 KVO 。