这是我的设置: - 一个UIView类型的类,它将绘制CAShapeLayer - 视图在我的视图控制器中呈现,并使用自动布局约束构建
我已经尝试使用layoutIfNeeded,但好像把数据传得太晚了,以至于视图无法被绘制。我还尝试在vieWillLayoutSubviews()中重新绘制视图,但是没有效果。下面是示例代码。我错在哪里了?
我是不是把数据传得太早或太晚了? 我是不是在太晚的时候绘制bezierPath?
我非常感谢指导。
也许还有一个后续问题:是否有更简单的方法来绘制一个与其视图大小绑定的圆形路径?
在我的视图控制器中:
import UIKit
class ViewController: UIViewController {
let buttonView: CircleButton = {
let view = CircleButton()
view.backgroundColor = .black
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewWillLayoutSubviews() {
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(buttonView)
buttonView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
buttonView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
buttonView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.75).isActive = true
buttonView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.25).isActive = true
buttonView.layoutIfNeeded()
buttonView.arcCenter = buttonView.center
buttonView.radius = buttonView.frame.width/2
}
override func viewDidAppear(_ animated: Bool) {
print(buttonView.arcCenter)
print(buttonView.radius)
}
}
按钮视图的类为:
class CircleButton: UIView {
//Casting outer circular layers
let trackLayer = CAShapeLayer()
var arcCenter = CGPoint()
var radius = CGFloat()
//UIView Init
override init(frame: CGRect) {
super.init(frame: frame)
}
//UIView post init
override func layoutSubviews() {
super.layoutSubviews()
print("StudyButtonView arcCenter \(arcCenter)")
print("StudyButtonView radius \(radius)")
layer.addSublayer(trackLayer)
let outerCircularPath = UIBezierPath(arcCenter: arcCenter, radius: radius, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
trackLayer.path = outerCircularPath.cgPath
trackLayer.strokeColor = UIColor.lightGray.cgColor
trackLayer.lineWidth = 5
trackLayer.strokeStart = 0
trackLayer.strokeEnd = 1
trackLayer.fillColor = UIColor.clear.cgColor
trackLayer.transform = CATransform3DMakeRotation(-CGFloat.pi/2, 0, 0, 1)
}
//Required for subclass
required init?(coder aDecoder: NSCoder) {
fatalError("has not been implemented")
}
}
init(coder:)
。当您以编程方式创建它(或在IB中进行实时查看)时,会调用init(frame:)
。这是两种完全不同的视图创建方式,我们希望无论您使用哪种方式都能正常工作。 - RoblayoutIfNeeded
- 你会怎样做?"...我不确定你指的是什么。我只在定义了约束的视图上动画时使用layoutIfNeeded
。但这里你没有这样做,所以我们不需要它。我谈论的唯一事情就是在didSet
观察器中可选地调用setNeedsLayout
。例如,在我的lineWidth
观察器中,我可以调用setNeedsLayout
,这将导致调用layoutSubviews
。在这种情况下,调用updatePath
更清晰,但它是一个替代方案。 - Rob