How to draw a circle using CAShapeLayer to be centered in a custom UIView in swift programmatically
我正在尝试使用 CAShapeLayer 在已自动约束的自定义 UIView 中绘制圆形进度条,我不想在我的超级视图的中心绘制我的圆圈,而是在我的自定义视图的中心因为我在上面有其他视图,所以下面的代码绘制了一个圆圈,但它没有定位在指定的视图中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // Custom View let gaugeViewHolder = UIView() scrollView.addSubview(gaugeViewHolder) gaugeViewHolder.translatesAutoresizingMaskIntoConstraints = false gaugeViewHolder.backgroundColor = UIColor.black gaugeViewHolder.leadingAnchor.constraint(equalTo: motherView.leadingAnchor).isActive = true gaugeViewHolder.topAnchor.constraint(equalTo: defaultAccImage.bottomAnchor, constant: 70).isActive = true gaugeViewHolder.trailingAnchor.constraint(equalTo: motherView.trailingAnchor).isActive = true gaugeViewHolder.heightAnchor.constraint(equalToConstant: 200).isActive = true //Now my circle let shapeLayer = CAShapeLayer() let centerForGauge = gaugeViewHolder.center let circularPath = UIBezierPath(arcCenter: centerForGauge , radius: 80, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: true) shapeLayer.path = circularPath.cgPath shapeLayer.strokeColor = UIColor.white.withAlphaComponent(0.20).cgColor shapeLayer.lineWidth = 10 shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.lineCap = kCALineCapRound gaugeViewHolder.layer.addSublayer(shapeLayer) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | let gaugeViewHolder = UIView() override func viewDidLoad() { super.viewDidLoad() scrollView.addSubview(gaugeViewHolder) gaugeViewHolder.translatesAutoresizingMaskIntoConstraints = false gaugeViewHolder.backgroundColor = UIColor.black gaugeViewHolder.leadingAnchor.constraint(equalTo: motherView.leadingAnchor).isActive = true gaugeViewHolder.topAnchor.constraint(equalTo: defaultAccImage.bottomAnchor, constant: 70).isActive = true gaugeViewHolder.trailingAnchor.constraint(equalTo: motherView.trailingAnchor).isActive = true gaugeViewHolder.heightAnchor.constraint(equalToConstant: 200).isActive = true } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let shapeLayer = CAShapeLayer() let centerForGauge = gaugeViewHolder.center print("gauge width:: \\(centerForGauge)") let circularPath = UIBezierPath(arcCenter: CGPoint(x: gaugeViewHolder.frame.size.width/2, y: gaugeViewHolder.frame.size.height/2) , radius: 100, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: true) shapeLayer.path = circularPath.cgPath shapeLayer.strokeColor = UIColor.white.withAlphaComponent(0.50).cgColor shapeLayer.lineWidth = 10 shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.lineCap = kCALineCapRound gaugeViewHolder.layer.addSublayer(shapeLayer) } |
你永远不会设置形状图层的框架。如果您希望形状层覆盖视图的矩形,它应该是拥有视图的边界矩形。
以下代码将形状层添加到我在示例应用故事板中添加并连接为 IBOutlet 的视图中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | @IBOutlet weak var gaugeViewHolder: UIView! override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) gaugeViewHolder.backgroundColor = UIColor.lightGray //Now my circle let shapeLayer = CAShapeLayer() shapeLayer.borderWidth = 2.0 //Add a box on the shape layer so you can see where it gets drawn. shapeLayer.frame = gaugeViewHolder.bounds //Use the view's bounds as the layer's frame //Convert gaugeViewHolder's center from it's superview's coordinate system to it's coordinate system let centerForGauge = gaugeViewHolder?.superview?.convert(gaugeViewHolder.center, to: gaugeViewHolder) ?? CGPoint.zero let lineWidth = CGFloat(5.0) //Use 1/2 the shortest side of the shapeLayer's frame for the radius, inset for the circle path's thickness. let radius = max(shapeLayer.frame.size.width, shapeLayer.frame.size.height)/2.0 - lineWidth / 2.0 let circularPath = UIBezierPath(arcCenter: centerForGauge , radius: radius, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: true) shapeLayer.path = circularPath.cgPath shapeLayer.strokeColor = UIColor.black.cgColor shapeLayer.lineWidth = lineWidth shapeLayer.fillColor = UIColor.yellow.cgColor shapeLayer.lineCap = .round gaugeViewHolder.layer.addSublayer(shapeLayer) } |
我更改了周围的颜色和 alpha,并在形状图层中添加了一个边框宽度,以使所有内容都脱颖而出。
如果您没有在设计时自行设置框架,您可以考虑在所有约束都应用到您的视图之后再添加该层。正如我在一个示例中测试过的那样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | var gaugeViewHolder : UIView! override func viewDidLoad() { super.viewDidLoad() gaugeViewHolder = UIView() scrollView.addSubview(gaugeViewHolder) gaugeViewHolder.translatesAutoresizingMaskIntoConstraints = false gaugeViewHolder.backgroundColor = UIColor.black gaugeViewHolder.leadingAnchor.constraint(equalTo: motherView.leadingAnchor).isActive = true gaugeViewHolder.topAnchor.constraint(equalTo: defaultAccImage.bottomAnchor, constant: 70).isActive = true gaugeViewHolder.trailingAnchor.constraint(equalTo: motherView.trailingAnchor).isActive = true gaugeViewHolder.heightAnchor.constraint(equalToConstant: 200).isActive = true } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let shapeLayer = CAShapeLayer() let centerForGauge = gaugeViewHolder.center let circularPath = UIBezierPath(arcCenter: centerForGauge , radius: 80, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: true) shapeLayer.path = circularPath.cgPath shapeLayer.strokeColor = UIColor.white.withAlphaComponent(0.20).cgColor shapeLayer.lineWidth = 10 shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.lineCap = CAShapeLayerLineCap.round gaugeViewHolder.layer.addSublayer(shapeLayer) } |