我正在尝试创建 2 个层,它们相互堆叠并且位于自定义 View 类中。
图层的绘图效果很好,但我无法让它们根据使用自动布局设置的 View 位置调整它们的位置,其中 View 是在代码中创建的(无 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
,并且无需为 shapLayer
设置 frame
。
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
}
结果
注意:我使用了第一个没有KVO的ProgressView
类。
关于ios - CALayer 自动布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53148356/