简体   繁体   English

iOS:在受约束的子视图中居中 CAShapeLayer

[英]iOS: centering CAShapeLayer inside a constrained subview

I'm trying to render a shape in the center of Circle, a custom subclass of UIView (first snippet).我正在尝试在 Circle 的中心渲染一个形状,这是 UIView 的自定义子类(第一个片段)。 Then I'm adding the Circle as a subview in my VC and adding constraints (second snippet).然后我将 Circle 添加为我的 VC 中的子视图并添加约束(第二个片段)。

When height and width is constrained, the rendered shape has its center (undesirably) in the top left corner of the Circle view (picture bellow).当高度和宽度受到约束时,渲染形状的中心(不希望出现)在圆形视图的左上角(如下图)。 When only X and Y of the Circle view are constrained, the shape is in center as expected.当仅约束圆形视图的 X 和 Y 时,形状按预期位于中心。

Why does this happen and what do I do to be able to constrain Circle as I please but still have the shape render in the center of Circle?为什么会发生这种情况,我该怎么做才能随意约束圆形,但形状仍呈现在圆形的中心? Thanks.谢谢。

Circle:圆圈:

class Circle: UIView {

func render(){
    let shapeLayer = CAShapeLayer()
    let center = self.center
    let endAngle = 2 * CGFloat.pi
    let circularPath = UIBezierPath(arcCenter: center, radius: 100, startAngle: 0, endAngle: endAngle, clockwise: true)

    shapeLayer.path = circularPath.cgPath
    self.layer.addSublayer(shapeLayer)
  }
}

VC:风险投资:

class VC: UIViewController {
let circle = Circle()

override func viewDidLoad() {
    super.viewDidLoad()        
    configure()
    circle.render()
}

func configure(){
    view.backgroundColor = .white
    view.addSubview(progressCircle)
    progressCircle.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        progressCircle.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        progressCircle.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        progressCircle.heightAnchor.constraint(equalToConstant: 200),
        progressCircle.widthAnchor.constraint(equalToConstant: 200)
    ])
  }
}

Result:结果:

结果

Here is fixed view (tested with Xcode 11.4 / Playground)这是固定视图(使用 Xcode 11.4 / Playground 测试)

class Circle: UIView {
    let shapeLayer = CAShapeLayer()

override func layoutSubviews() {
    super.layoutSubviews()
    shapeLayer.position = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
}

func render(){
    let center = self.center
    let endAngle = 2 * CGFloat.pi
    let circularPath = UIBezierPath(arcCenter: center, radius: 100, startAngle: 0, endAngle: endAngle, clockwise: true)

    shapeLayer.path = circularPath.cgPath
    self.layer.addSublayer(shapeLayer)
  }
}

Ended up with this solution bellow (different shape this time but the principle applies).以下面的解决方案结束(这次不同的形状,但原理适用)。 Work as expected, the view can now be constrained and moved in the VC however wanted.按预期工作,现在可以根据需要在 VC 中限制和移动视图。

class Circle: UIView {

private var layer: CAShapeLayer!
override func draw(_ rect: CGRect) {

    let width =  rect.width
    let height = rect.height        
    let lineWidth = 0.1 * min(width, height)
    let center = CGPoint(x: width / 2, y: height / 2)
    let radius = (min(width, height) - lineWidth) / 2
    let startAngle = -CGFloat.pi / 2
    let endAngle = startAngle + 2 * CGFloat.pi
    let circularPath = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)

    layer = CAShapeLayer()
    layer.path = circularPath.cgPath
    layer.strokeColor = UIColor.lightGray.cgColor
    layer.lineWidth = lineWidth
    layer.fillColor = UIColor.clear.cgColor
    layer.lineCap = .round

    layer.addSublayer(backbroundLayer)

  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM