如何获取已使用自动布局设置的 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 中使用? 谢谢!
几点观察:
center
属性是当前视图的中心在superview坐标系中的位置那不是可能是你想要的。您需要 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
,你可以在 storyboards/NIBs.
中渲染它
您可以尝试使用边界而不是框架。他们可能会帮你给出 UIVIew 的中心坐标。中心 属性 是当前视图的中心在父视图的坐标系内的位置。您可以尝试使用以下代码,它是当前视图的中点。
CGPoint(x: myView.bounds.midX, y: myView.bounds.midY),
所以我还没有看到关于此的任何其他 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 中使用? 谢谢!
几点观察:
center
属性是当前视图的中心在superview坐标系中的位置那不是可能是你想要的。您需要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
,你可以在 storyboards/NIBs. 中渲染它
您可以尝试使用边界而不是框架。他们可能会帮你给出 UIVIew 的中心坐标。中心 属性 是当前视图的中心在父视图的坐标系内的位置。您可以尝试使用以下代码,它是当前视图的中点。
CGPoint(x: myView.bounds.midX, y: myView.bounds.midY),