将约束设置为以编程方式完成的 arc UIBezierPath

Set constraints to arc UIBezierPath done programmatically

我正在开发一个自定义的圆形进度条,但我不知道将其居中到所有设备的进度标签的同一中心。因为它是一个CAShapeLayer,我不能使用SnapKit,也不能手动添加约束,至少我不能通过代码来做,它没有约束属性。

这是 iPhone 8 上的视图,如果我的故事板设置为 iPhone 8:

这是 iPhone X 上使用相同故事板设置的视图:

我的ViewController.swift:

import UIKit

class ViewController: UIViewController {

    let trackLayer = CAShapeLayer()

    @IBOutlet weak var percentageLoadedLabel: UILabel!
    @IBOutlet weak var uiView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        createCircleProgressBar()
    }

    //MARK: Init track
    func createCircleProgressBar() {
        let center = percentageLoadedLabel.center

        let circularPath = UIBezierPath(arcCenter: center, radius: 100, startAngle: -CGFloat.pi/2, endAngle: 3*CGFloat.pi/2, clockwise: true)

        trackLayer.path = circularPath.cgPath
        trackLayer.lineCap = kCALineCapRound
        trackLayer.fillColor = UIColor.clear.cgColor
        trackLayer.strokeColor = UIColor.lightGray.cgColor
        trackLayer.lineWidth = 10

        uiView.layer.addSublayer(trackLayer)
    }
}

它在其他设备上也有一些偏移,但是当我将故事板更改为 iPhone X 时,它工作正常,仅适用于此设备,看起来 let center = percentageLoadedLabel.center 行得到了在故事板上设计的中心,在它被约束更新之前。

我试图在故事板上添加一个 UIView 并在其中添加两个元素(UILabelCAShapeLayer)以获得中心 属性,但它没有没用。

我已经为此苦苦挣扎了几天,我也尝试使用 @IBDesignable 来做到这一点,但我遇到了同样的问题。如果有人可以帮助我,我将不胜感激!

尝试将 createCircleProgressBar() 方法调用移动到 ViewDidAppear 问题是视图在 viewDidLoad()

中没有完全布局

您最好将此实现移至自定义视图,并在故事板中将 uiView class 设置为您的自定义视图 class。

viewDidLayoutSubviews()

是获得视图中心的最佳位置。

你说得对:

it looks like the line let center = percentageLoadedLabel.center gets the center designed on the storyboard, before it is updated by the constraints.

viewDidLoad 中您还不知道视图的正确大小,因此您还不能依赖 centerbounds frame 等等.

但是,有方法viewDidLayoutSubviews(已记录here)。

如其所说:

Called to notify the view controller that its view has just laid out its subviews.

所以,如果我将你的呼叫从 createCircleProgressBar() 转移到 viewDidLayoutSubview(),就像这样:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    createCircleProgressBar()
}

我在 iPhone 8 plus

上看到了这个

这在 iPhone X

它在 iPhone 8 上看起来也不错 :)

希望对你有所帮助。