如何使用 CAShapeLayer 以编程方式在 swift 中的自定义 UIView 中居中绘制圆
How to draw a circle using CAShapeLayer to be centered in a custom UIView in swift programmatically
我正在尝试在自动约束的自定义 UIView 中使用 CAShapeLayer 绘制一个圆形进度条,我不想在我的超级视图的中心绘制我的圆圈,而是在我的自定义视图的中心视图,因为我在上面还有其他视图我下面的代码画了一个圆圈,但它没有定位在指定的视图中
// 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)
如果您在设计时没有自己设置框架,您可以考虑在所有约束应用到您的视图之后再添加图层。正如我在示例中测试的那样有效。
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)
}
您从未设置形状图层的边框。如果您希望形状层覆盖视图的矩形,它应该是拥有视图的边界矩形。
下面是将形状图层添加到我在示例应用故事板中添加并连接为 IBOutlet 的视图的代码:
@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,并向形状图层添加了 borderWidth 以使一切都突出。
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)
}
我正在尝试在自动约束的自定义 UIView 中使用 CAShapeLayer 绘制一个圆形进度条,我不想在我的超级视图的中心绘制我的圆圈,而是在我的自定义视图的中心视图,因为我在上面还有其他视图我下面的代码画了一个圆圈,但它没有定位在指定的视图中
// 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)
如果您在设计时没有自己设置框架,您可以考虑在所有约束应用到您的视图之后再添加图层。正如我在示例中测试的那样有效。
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)
}
您从未设置形状图层的边框。如果您希望形状层覆盖视图的矩形,它应该是拥有视图的边界矩形。
下面是将形状图层添加到我在示例应用故事板中添加并连接为 IBOutlet 的视图的代码:
@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,并向形状图层添加了 borderWidth 以使一切都突出。
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)
}