如何获取已使用自动布局设置的 UIView 的中心点(CGPoint)

How to get center point (CGPoint) of a UIView that has been set using autolayout

所以我还没有看到关于此的任何其他 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属性是当前视图的中心在superview坐标系中的位置那不是可能是你想要的。您需要 CGPoint(x: myView.bounds.midX, y: myView.bounds.midY),它是 current 视图的中点。

  2. 因为您正在使用约束,所以您需要将路径的创建推迟到应用约束之后,因为那是设置视图的 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,你可以在 storyboards/NIBs.

  • 中渲染它

您可以尝试使用边界而不是框架。他们可能会帮你给出 UIVIew 的中心坐标。中心 属性 是当前视图的中心在父视图的坐标系内的位置。您可以尝试使用以下代码,它是当前视图的中点。

CGPoint(x: myView.bounds.midX, y: myView.bounds.midY),