如何获取已使用自动布局设置的 UIView 的中心点(CGPoint)
Posted
技术标签:
【中文标题】如何获取已使用自动布局设置的 UIView 的中心点(CGPoint)【英文标题】:How to get center point (CGPoint) of a UIView that has been set using autolayout 【发布时间】:2020-05-21 06:10:57 【问题描述】:所以我还没有看到任何其他关于此的 SO 问题。基本上,我以编程方式设置了一个带有自动布局的 UIView。
当我尝试创建 UIBezierPath 时出现问题:
let circularPath = UIBezierPath(arcCenter: myView.center, radius: (91*(1.2))/2 - (8/2), startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)
问题是 myView.center 打印出:0.0, 0.0
,因为我没有为 myView 设置 CGRect .frame,而是使用了自动布局(如下所示):
NSLayoutConstraint.activate([
myView.heightAnchor.constraint(equalToConstant: 91),
myView.widthAnchor.constraint(equalToConstant: 91),
myView.centerXAnchor.constraint(equalToSystemSpacingAfter: myButton.centerXAnchor, multiplier: 1),
myView.centerYAnchor.constraint(equalToSystemSpacingBelow: myButton.centerYAnchor, multiplier: 1),
])
也许我应该注意到 myView 是作为 myButton 的子视图添加的(尽管这并不重要..)
那么我该如何做呢?我怎样才能让 .center(一种 CGPoint 类型)在 UIBezierPath 中使用?谢谢!
【问题讨论】:
【参考方案1】:一些观察:
center
属性是当前视图的中心在父视图的坐标系中的位置。这可能不是您想要的。您需要CGPoint(x: myView.bounds.midX, y: myView.bounds.midY)
,它是current 视图的中点。
因为您正在使用约束,所以您需要将路径的创建推迟到应用约束之后,因为那是设置视图的 bounds
的时间。典型的解决方案是实现UIButton
子类,在该子类中您可以实现layoutSubviews
,并在那里设置路径。
例如,一个简单的圆形按钮可能定义如下:
@IBDesignable
class CircleButton: UIButton
let normalColor: UIColor = .red
let highlightedColor: UIColor = .init(red: 0.5, green: 0, blue: 0, alpha: 1)
lazy var shapeLayer: CAShapeLayer =
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = normalColor.cgColor
return shapeLayer
()
override init(frame: CGRect = .zero)
super.init(frame: frame)
configure()
required init?(coder: NSCoder)
super.init(coder: coder)
configure()
func configure()
layer.addSublayer(shapeLayer)
override func layoutSubviews()
super.layoutSubviews()
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let radius = min(bounds.height, bounds.width) / 2
shapeLayer.path = UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: 2 * .pi, clockwise: true).cgPath
override var isHighlighted: Bool
didSet
if isHighlighted
shapeLayer.fillColor = highlightedColor.cgColor
else
shapeLayer.fillColor = normalColor.cgColor
这种方法的优点是:
您的视图控制器没有大量用于渲染圆圈的代码。
无论渲染的大小如何,这都会起作用(如果您的约束不是针对固定大小,但可能会响应设备的方向、大小类等,这可能很有用)。
如果您愿意,因为这是@IBDesignable
,您可以在情节提要/NIB 中呈现它。
【讨论】:
我明白了。我想我应该给你更多信息:我当然在做 myView.center 之前设置了 myView 自动布局。哦,好的,作为对2.)的回应,是不是不可能做一些像myView.center这样简单的事情来获得一个自动布局视图的CGPoint? @GEOG - 从理论上讲,如果您在设置约束后调用了layoutIfNeeded
,那么应该设置bounds
,然后bounds.midX
和bounds.midY
应该返回正确的值。但它有点脆弱,对尺寸变化没有反应(例如,如果你的圆形视图的约束与屏幕上的其他东西成比例,而不是固定的宽度和高度。但是有很多方法可以完成你想要的。我d 个人会把它放在一个按钮子类中,回复layoutSubviews
,你就有了一个很好的、灵活的、通用的解决方案。
是的,是我没有执行 myView.layoutIfNeeded()。它现在起作用了!也感谢你的课堂方法!【参考方案2】:
您可以尝试使用边界而不是框架。它们可能会帮助您提供 UIVIew 的中心坐标。 center 属性是当前视图的中心在父视图坐标系中的位置。您可以尝试使用以下代码,它是当前视图的中点。
CGPoint(x: myView.bounds.midX, y: myView.bounds.midY),
【讨论】:
以上是关于如何获取已使用自动布局设置的 UIView 的中心点(CGPoint)的主要内容,如果未能解决你的问题,请参考以下文章
如何使用自动布局将 UIView 定位在其他两个 UIView 的中心?
如何获取使用自动布局的 UIView 的 x、y、宽度、高度