如何确定UIBezierPath的arcCenter相对于其父视图的正确坐标
问题原因
你之前的写法报错是因为centerXAnchor、centerYAnchor是Auto Layout的锚点对象,而非CGFloat类型的坐标数值,直接传入CGPoint初始化方法会出现类型不匹配错误。
此外通过Auto Layout约束布局的视图,在viewDidLoad阶段约束还未完成计算,此时获取的frame、center、bounds都是初始值,不会符合最终布局结果,你需要在视图布局完成的生命周期节点获取准确坐标,再更新CAShapeLayer的路径。
实现方案
假设你要放置圆形进度条的蓝色框目标视图为progressContainerView,你已经为其添加了符合需求的Auto Layout约束,按照以下步骤实现即可适配多设备尺寸:
- 提前将CAShapeLayer声明为全局属性,避免布局更新时重复创建
// 控制器属性 private let circleLayer = CAShapeLayer() private let progressContainerView = UIView() // 你的蓝色框目标视图
- 在
viewDidLoad中完成基础配置和约束添加
override func viewDidLoad() { super.viewDidLoad() // 配置目标容器视图约束,和你其他元素的约束写法一致 progressContainerView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(progressContainerView) NSLayoutConstraint.activate([ // 此处替换为你实际需要的约束规则 progressContainerView.widthAnchor.constraint(equalToConstant: 200), progressContainerView.heightAnchor.constraint(equalToConstant: 200), progressContainerView.centerXAnchor.constraint(equalTo: view.centerXAnchor), progressContainerView.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) // 配置layer固定属性,不需要每次布局重复修改 circleLayer.fillColor = UIColor.clear.cgColor circleLayer.strokeColor = UIColor.systemBlue.cgColor circleLayer.lineWidth = 4 progressContainerView.layer.addSublayer(circleLayer) }
- 在布局完成的生命周期方法中更新路径,此时获取的坐标是准确值
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 获取目标视图自身坐标系的中点,作为圆形的中心 let center = CGPoint(x: progressContainerView.bounds.midX, y: progressContainerView.bounds.midY) // 动态计算半径,适配容器尺寸,避免超出视图范围 let radius = min(progressContainerView.bounds.width, progressContainerView.bounds.height) / 2 - circleLayer.lineWidth // 生成路径赋值给layer let circlePath = UIBezierPath(arcCenter: center, radius: radius, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true) circleLayer.path = circlePath.cgPath }
注意事项
- 如果你是自定义UIView作为进度条容器,只需要把更新路径的逻辑写在自定义View的
layoutSubviews方法中即可,逻辑完全一致 - 如果你确实需要获取目标视图相对于父视图的中心坐标,直接调用
progressContainerView.center即可,该属性本身就是父视图坐标系下的CGPoint值 - 该方案会自动适配屏幕旋转、动态尺寸变化等场景,不会出现错位问题
内容的提问来源于stack exchange,提问作者forrest
相关产品推荐
相关产品推荐

