使用编程约束创建视图会导致内容绘制在错误的位置
Creating view with programmatic constraints causes the content to be drawn in the wrong place
我正在将自定义视图添加到另一个视图,该视图随后以编程方式设置了其约束。这导致视图的内容绘制在错误的位置,我不确定为什么。这是我拥有的代码以及到目前为止我尝试过的代码:
// Called in viewDidLoad
let buttonView = UIView()
buttonView.translatesAutoresizingMaskIntoConstraints = false
let ring = CircularProgressView()
ring.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
ring.backgroundColor = .yellow
buttonView.addSubview(ring)
self.view.addSubview(buttonView)
NSLayoutConstraint.activate([
buttonView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12),
buttonView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -28),
buttonView.heightAnchor.constraint(equalToConstant: 80),
buttonView.widthAnchor.constraint(equalToConstant: 80),
ring.centerXAnchor.constraint(equalTo: buttonView.centerXAnchor),
ring.centerYAnchor.constraint(equalTo: buttonView.centerYAnchor)
])
我尝试调用 ring.layoutIfNeeded() 或使用约束设置环形视图的宽度和高度,但没有任何改变。
ring.heightAnchor.constraint(equalToConstant: 80),
ring.widthAnchor.constraint(equalToConstant: 80)
CircularProgressView class 看起来像这样。我尝试在此处使用边界而不是框架,或者不将值减半并再次保持不变。
class CircularProgressView: UIView {
// First create two layer properties
private var circleLayer = CAShapeLayer()
private var progressLayer = CAShapeLayer()
private var currentValue: Double = 0
override init(frame: CGRect) {
super.init(frame: frame)
createCircularPath()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
createCircularPath()
}
func createCircularPath() {
let circularPath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0),
radius: 41,
startAngle: -.pi / 2,
endAngle: 3 * .pi / 2,
clockwise: true)
circleLayer.path = circularPath.cgPath
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.lineCap = .round
circleLayer.lineWidth = 3.0
circleLayer.strokeColor = UIColor.black.withAlphaComponent(0.2).cgColor
progressLayer.path = circularPath.cgPath
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.lineCap = .round
progressLayer.lineWidth = 3.0
progressLayer.strokeEnd = 0
progressLayer.strokeColor = UIColor.black.cgColor
layer.addSublayer(circleLayer)
layer.addSublayer(progressLayer)
let circularProgressAnimation = CABasicAnimation(keyPath: "strokeEnd")
circularProgressAnimation.duration = 2
circularProgressAnimation.toValue = 1
circularProgressAnimation.fillMode = .forwards
circularProgressAnimation.isRemovedOnCompletion = false
progressLayer.add(circularProgressAnimation, forKey: "progressAnim")
progressLayer.pauseAnimation()
}
}
如果通过故事板完成,这一切都没有问题,但我需要为这个用例以编程方式创建它,我对哪里出了问题有点困惑。
您需要以编程方式使两个视图都像
// Called in viewDidLoad
let buttonView = UIView()
buttonView.translatesAutoresizingMaskIntoConstraints = false
let ring = CircularProgressView()
ring.translatesAutoresizingMaskIntoConstraints = false
ring.backgroundColor = .yellow
buttonView.addSubview(ring)
self.view.addSubview(buttonView)
NSLayoutConstraint.activate([
buttonView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12),
buttonView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -28),
buttonView.heightAnchor.constraint(equalToConstant: 80),
buttonView.widthAnchor.constraint(equalToConstant: 80),
ring.centerXAnchor.constraint(equalTo: buttonView.centerXAnchor),
ring.centerYAnchor.constraint(equalTo: buttonView.centerYAnchor),
ring.heightAnchor.constraint(equalToConstant: 80),
ring.widthAnchor.constraint(equalToConstant: 80)
])
并仅在 layoutSubviews
内调用 createCircularPath
override func layoutSubviews() {
super.layoutSubviews()
createCircularPath()
}
也尝试将 CircularProgressView
的 translatesAutoresizingMaskIntoConstraints
属性 设置为 false
:
ring.translatesAutoresizingMaskIntoConstraints = false
我正在将自定义视图添加到另一个视图,该视图随后以编程方式设置了其约束。这导致视图的内容绘制在错误的位置,我不确定为什么。这是我拥有的代码以及到目前为止我尝试过的代码:
// Called in viewDidLoad
let buttonView = UIView()
buttonView.translatesAutoresizingMaskIntoConstraints = false
let ring = CircularProgressView()
ring.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
ring.backgroundColor = .yellow
buttonView.addSubview(ring)
self.view.addSubview(buttonView)
NSLayoutConstraint.activate([
buttonView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12),
buttonView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -28),
buttonView.heightAnchor.constraint(equalToConstant: 80),
buttonView.widthAnchor.constraint(equalToConstant: 80),
ring.centerXAnchor.constraint(equalTo: buttonView.centerXAnchor),
ring.centerYAnchor.constraint(equalTo: buttonView.centerYAnchor)
])
我尝试调用 ring.layoutIfNeeded() 或使用约束设置环形视图的宽度和高度,但没有任何改变。
ring.heightAnchor.constraint(equalToConstant: 80),
ring.widthAnchor.constraint(equalToConstant: 80)
CircularProgressView class 看起来像这样。我尝试在此处使用边界而不是框架,或者不将值减半并再次保持不变。
class CircularProgressView: UIView {
// First create two layer properties
private var circleLayer = CAShapeLayer()
private var progressLayer = CAShapeLayer()
private var currentValue: Double = 0
override init(frame: CGRect) {
super.init(frame: frame)
createCircularPath()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
createCircularPath()
}
func createCircularPath() {
let circularPath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0),
radius: 41,
startAngle: -.pi / 2,
endAngle: 3 * .pi / 2,
clockwise: true)
circleLayer.path = circularPath.cgPath
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.lineCap = .round
circleLayer.lineWidth = 3.0
circleLayer.strokeColor = UIColor.black.withAlphaComponent(0.2).cgColor
progressLayer.path = circularPath.cgPath
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.lineCap = .round
progressLayer.lineWidth = 3.0
progressLayer.strokeEnd = 0
progressLayer.strokeColor = UIColor.black.cgColor
layer.addSublayer(circleLayer)
layer.addSublayer(progressLayer)
let circularProgressAnimation = CABasicAnimation(keyPath: "strokeEnd")
circularProgressAnimation.duration = 2
circularProgressAnimation.toValue = 1
circularProgressAnimation.fillMode = .forwards
circularProgressAnimation.isRemovedOnCompletion = false
progressLayer.add(circularProgressAnimation, forKey: "progressAnim")
progressLayer.pauseAnimation()
}
}
如果通过故事板完成,这一切都没有问题,但我需要为这个用例以编程方式创建它,我对哪里出了问题有点困惑。
您需要以编程方式使两个视图都像
// Called in viewDidLoad
let buttonView = UIView()
buttonView.translatesAutoresizingMaskIntoConstraints = false
let ring = CircularProgressView()
ring.translatesAutoresizingMaskIntoConstraints = false
ring.backgroundColor = .yellow
buttonView.addSubview(ring)
self.view.addSubview(buttonView)
NSLayoutConstraint.activate([
buttonView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12),
buttonView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -28),
buttonView.heightAnchor.constraint(equalToConstant: 80),
buttonView.widthAnchor.constraint(equalToConstant: 80),
ring.centerXAnchor.constraint(equalTo: buttonView.centerXAnchor),
ring.centerYAnchor.constraint(equalTo: buttonView.centerYAnchor),
ring.heightAnchor.constraint(equalToConstant: 80),
ring.widthAnchor.constraint(equalToConstant: 80)
])
并仅在 layoutSubviews
createCircularPath
override func layoutSubviews() {
super.layoutSubviews()
createCircularPath()
}
也尝试将 CircularProgressView
的 translatesAutoresizingMaskIntoConstraints
属性 设置为 false
:
ring.translatesAutoresizingMaskIntoConstraints = false