如何确定 UIBezierPath 相对于其父视图的 arcCenter?
Posted
技术标签:
【中文标题】如何确定 UIBezierPath 相对于其父视图的 arcCenter?【英文标题】:How do I determine the arcCenter for a UIBezierPath relative to its parent view? 【发布时间】:2021-11-17 05:42:32 【问题描述】:我正在使用带有 UIBezierPath 的 CAShapeLayer 来制作圆形进度条。该代码需要基于 CGPoint 的 center 值。
let circleLayer = CAShapeLayer()
let circlePath = UIBezierPath(arcCenter: center, radius: 100, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
我已手动设置值如下:
let center = CGPoint(x: 70, y: 70)
但是这些值是相对于 superView 的,我需要使其相对于它的父 UIView。
UIView 中的所有其他元素都使用这样的编程 UI 代码进行约束:
sampleText.translatesAutoresizingMaskIntoConstraints = false
sampleText.topAnchor.constraint(equalTo: directionsTitle.bottomAnchor, constant: 0).isActive = true
sampleText.leadingAnchor.constraint(equalTo: timerFooter.leadingAnchor, constant: 8).isActive = true
sampleText.trailingAnchor.constraint(equalTo: timerFooter.trailingAnchor, constant: -8).isActive = true
固定值可能在一台设备上正常工作,但在更大或更小的设备上会不对齐。我的问题是,如何确定 UIView 的 center 的值将满足 CGPoint 所需的值?
我试过这个:
let centerX = view.centerXAnchor
let centerY = view.centerYAnchor
let center = CGPoint(x: centerX, y: centerY)
但是,这会引发错误:对初始化程序的调用中没有完全匹配
下图反映了形状放置的相对位置。蓝色框表示我想要放置圆圈的所需 UIView 区域。
非常感谢有智慧人士的建议。
【问题讨论】:
我不是 100% 关注您的描述。当您说 superView 和父 UIView 时...它们不是一回事吗?用这么小的 sn-ps 代码很难理解。我可以澄清一下...您是否有一个名为CircularProgressView
的 UIView?在那里你定义CAShapeLayer
?然后您想将CircularProgressView
放在另一个视图中(称为OuterView
)?但是您希望CAShapeLayer
的中心与OuterView
的中心对齐?请您显示更多代码或一些屏幕截图或其他内容吗?谢谢
抱歉混淆了。我添加了一个屏幕截图,显示了圆圈的所需放置区域。蓝色框是情节提要中的 UIView。 CGPoint 是相对于整个视图的,我需要弄清楚如何相对于 UIView 放置它。
不用担心。我想我解决了你的问题,我建议不要像这样使用 CAShapeLayers,而是创建你自己的自定义 UIView 包含 CAShapeLayer 并使用该视图来定位它。这是使用 CALayers 的标准方式。我已经为你写了一个简短的答案。
【参考方案1】:
啊,好吧,我想我明白你面临的问题是什么了。
我认为您的问题是您尝试使用 CAShapeLayer
,就像它是 UIView 一样。而实际上他们根本不会那样做。
您应该做的是创建一个 UIView 子类并将CAShapeLayer
放在那里。现在您只需要担心CAShapeLayer
如何适合它自己的 UIView 子类。
要将图层“定位”到其他视图中,您实际上根本不需要担心这一点。您只需放置新的 UIView 子类,图层就会随之而来。
例如
class MyProgressView: UIView
let circleLayer: CAShapeLayer
// add the circleLayer
// add properties for customising the circle layer
// Position the circle layer in the centre of the MyProgressView frame
// I'd suggest using `layoutSubviews` or something for this.
// etc...
现在...要定位您实际上不需要的“CircleLayer”。您只需将 MyProgressView
定位在您想要的位置,图层就是其中的一部分,因此可以继续使用。
从您的屏幕截图看来,您希望带有蓝色矩形的视图包含 circleLayer。如果是这种情况,那么让蓝色矩形查看您的自定义 UIView 子类并......完成。它现在将包含圆形视图。
RayWenderlich 有一些关于使用 CALayer 自定义视图的好东西...https://www.raywenderlich.com/10317653-calayer-tutorial-for-ios-getting-started#toc-anchor-002
【讨论】:
我曾考虑过这样的事情,但这解决了问题。谢谢。【参考方案2】:听起来你想要 UIView 的 bounds
的中点,我认为是 yourView.bounds.midX
和 yourView.bounds.midY
视图的bounds
是它自己的坐标空间。视图的frame
是它在其父空间中的位置。
UIView
有类似convertPoint:toCoordinateSpace:
和朋友的方法,用于在这些空间之间转换点和矩形。
【讨论】:
以上是关于如何确定 UIBezierPath 相对于其父视图的 arcCenter?的主要内容,如果未能解决你的问题,请参考以下文章