Swift 3 - 自定义 UIButton 半径删除约束?
Swift 3 - Custom UIButton radius deletes constraints?
我的视图控制器拥有一个带有 3 个按钮的堆栈视图。一个固定在中央,宽度固定,stackview 设置为按比例填充,这样其他两个按钮将是对称的。
不过,我也在自定义按钮的角半径,一旦应用程序加载,按钮就会以不希望的方式调整大小。
我尝试了很多堆栈视图分布和填充设置。从堆栈视图中删除按钮并简单地尝试将它们限制在普通 UIView 上的边缘似乎无济于事,但不确定是否删除了限制。
从视觉上看,按钮将位于屏幕的右下角,边缘和按钮之间的距离为 0 space。目前它的布局方式在多个设备上似乎没有限制,导致它在较大的显示器上有一个 space,并在模拟器内的小显示器上退出屏幕。
尝试编码以达到所需的角落:
@IBOutlet fileprivate weak var button: UIButton! { didSet {
button.round(corners: [.topRight, .bottomLeft], radius: 50 , borderColor: UIColor.blue, borderWidth: 5.0)
button.setNeedsUpdateConstraints()
button.setNeedsLayout()
} }
override func viewDidLayoutSubviews() {
button.layoutIfNeeded()
}
ovverride func updateViewContraints() {
button.updateConstraintsIfNeeded()
super.updateViewConstraints()
}
正在使用的 UIView 扩展可以在这里找到:
有什么解决方案可以正确调整按钮的圆角半径'并允许约束将按钮更新为应有的状态。
没有看到你的完整代码,我怀疑你得到这个是因为它绘制了带有边框的多个图层,并且从不删除任何图层!如果按钮调整大小,旧层仍然存在。这是一个片段,显示在重绘时删除旧层,您应该能够适应。我在堆栈视图中对此进行了测试,它在旋转时也表现正确:
class RoundedCorner: UIButton {
var lastBorderLayer:CAShapeLayer?
override func layoutSubviews() { setup() }
func setup() {
let r = self.bounds.size.height / 2
let path = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .bottomRight],
cornerRadii: CGSize(width: r, height: r))
let mask = CAShapeLayer()
mask.path = path.cgPath
addBorder(mask: mask, borderColor: UIColor.blue, borderWidth: 5)
self.layer.mask = mask
}
func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
let borderLayer = CAShapeLayer()
borderLayer.path = mask.path
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = borderColor.cgColor
borderLayer.lineWidth = borderWidth
borderLayer.frame = bounds
if let last = self.lastBorderLayer, let index = layer.sublayers?.index(of: last) {
layer.sublayers?.remove(at: index)
}
layer.addSublayer(borderLayer)
self.lastBorderLayer = borderLayer
}
}
您在评论中还提到了应用延迟。我并不感到惊讶,因为布局可以在每次更新时被多次调用,并且您每次都在创建一个新层。您可以通过保存按钮框架的最后尺寸并进行比较来避免这种情况。如果相同,请不要重新创建图层。
我的视图控制器拥有一个带有 3 个按钮的堆栈视图。一个固定在中央,宽度固定,stackview 设置为按比例填充,这样其他两个按钮将是对称的。
不过,我也在自定义按钮的角半径,一旦应用程序加载,按钮就会以不希望的方式调整大小。
我尝试了很多堆栈视图分布和填充设置。从堆栈视图中删除按钮并简单地尝试将它们限制在普通 UIView 上的边缘似乎无济于事,但不确定是否删除了限制。
从视觉上看,按钮将位于屏幕的右下角,边缘和按钮之间的距离为 0 space。目前它的布局方式在多个设备上似乎没有限制,导致它在较大的显示器上有一个 space,并在模拟器内的小显示器上退出屏幕。
尝试编码以达到所需的角落:
@IBOutlet fileprivate weak var button: UIButton! { didSet {
button.round(corners: [.topRight, .bottomLeft], radius: 50 , borderColor: UIColor.blue, borderWidth: 5.0)
button.setNeedsUpdateConstraints()
button.setNeedsLayout()
} }
override func viewDidLayoutSubviews() {
button.layoutIfNeeded()
}
ovverride func updateViewContraints() {
button.updateConstraintsIfNeeded()
super.updateViewConstraints()
}
正在使用的 UIView 扩展可以在这里找到:
有什么解决方案可以正确调整按钮的圆角半径'并允许约束将按钮更新为应有的状态。
没有看到你的完整代码,我怀疑你得到这个是因为它绘制了带有边框的多个图层,并且从不删除任何图层!如果按钮调整大小,旧层仍然存在。这是一个片段,显示在重绘时删除旧层,您应该能够适应。我在堆栈视图中对此进行了测试,它在旋转时也表现正确:
class RoundedCorner: UIButton {
var lastBorderLayer:CAShapeLayer?
override func layoutSubviews() { setup() }
func setup() {
let r = self.bounds.size.height / 2
let path = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .bottomRight],
cornerRadii: CGSize(width: r, height: r))
let mask = CAShapeLayer()
mask.path = path.cgPath
addBorder(mask: mask, borderColor: UIColor.blue, borderWidth: 5)
self.layer.mask = mask
}
func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
let borderLayer = CAShapeLayer()
borderLayer.path = mask.path
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = borderColor.cgColor
borderLayer.lineWidth = borderWidth
borderLayer.frame = bounds
if let last = self.lastBorderLayer, let index = layer.sublayers?.index(of: last) {
layer.sublayers?.remove(at: index)
}
layer.addSublayer(borderLayer)
self.lastBorderLayer = borderLayer
}
}
您在评论中还提到了应用延迟。我并不感到惊讶,因为布局可以在每次更新时被多次调用,并且您每次都在创建一个新层。您可以通过保存按钮框架的最后尺寸并进行比较来避免这种情况。如果相同,请不要重新创建图层。