将约束设置为以编程方式完成的 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
并在其中添加两个元素(UILabel
和 CAShapeLayer
)以获得中心 属性,但它没有没用。
我已经为此苦苦挣扎了几天,我也尝试使用 @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
中您还不知道视图的正确大小,因此您还不能依赖 center
、bounds
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 上看起来也不错 :)
希望对你有所帮助。
我正在开发一个自定义的圆形进度条,但我不知道将其居中到所有设备的进度标签的同一中心。因为它是一个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
并在其中添加两个元素(UILabel
和 CAShapeLayer
)以获得中心 属性,但它没有没用。
我已经为此苦苦挣扎了几天,我也尝试使用 @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
中您还不知道视图的正确大小,因此您还不能依赖 center
、bounds
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 上看起来也不错 :)
希望对你有所帮助。