Swift:按钮圆角打破约束
Posted
技术标签:
【中文标题】Swift:按钮圆角打破约束【英文标题】:Swift: Button round corner breaks contraints 【发布时间】:2017-11-27 16:42:49 【问题描述】:我有一个表格视图,其中包含通过 xib 加载的自定义单元格,在该单元格中我有状态按钮,右下角应该是圆角的。该按钮的尾随/前导/底部空间限制为 superview=0 和 height=30。
如果不四舍五入,它就可以完美地工作,只要我将一个角(例如右下角)转角,约束就会中断
self.btnStatus.roundCorners(corners: [.bottomRight], radius: 7.0, borderWidth: nil, borderColor: nil)
这里有些人建议调用 layoutSubviews() 但它没有帮助我。
更具体地说,我创建了一个简单的项目,您可以在其中查看整个项目。
正确链接
ButtonRoundCorner.zip
【问题讨论】:
关于打破约束的错误是什么? 无需查看您的代码,如果它违反了约束,只需将其放在UIView
中,并为该容器 UIView
提供约束。约束不会关心视图内部的内容,圆角与否。
@benjiiiii:完全没有错误,只是按钮没有对齐...
@mihatel - 您的“保管箱”链接错误...您必须选择“分享”然后创建一个链接。
@mihatel - 看看我的回答。我想你会发现它是一种更可靠的方法。
【参考方案1】:
您可以通过将按钮子类化并通过覆盖其layoutSubviews()
函数放置“舍入”代码来获得更可靠的结果。
首先,如果你想添加一个边框,你不想添加多个“边框子层”......所以将你的 UIView
扩展名更改为:
extension UIView
func roundCorners(corners: UIRectCorner, radius: CGFloat, borderWidth: CGFloat?, borderColor: UIColor?)
let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let maskLayer = CAShapeLayer()
maskLayer.frame = self.bounds
maskLayer.path = maskPath.cgPath
self.layer.mask = maskLayer
self.layer.masksToBounds = true
if (borderWidth != nil && borderColor != nil)
// remove previously added border layer
for layer in layer.sublayers!
if layer.name == "borderLayer"
layer.removeFromSuperlayer()
let borderLayer = CAShapeLayer()
borderLayer.frame = self.bounds;
borderLayer.path = maskPath.cgPath;
borderLayer.lineWidth = borderWidth ?? 0;
borderLayer.strokeColor = borderColor?.cgColor;
borderLayer.fillColor = UIColor.clear.cgColor;
borderLayer.name = "borderLayer"
self.layer.addSublayer(borderLayer);
接下来,添加一个UIButton
子类:
class RoundedButton: UIButton
var corners: UIRectCorner?
var radius = CGFloat(0.0)
var borderWidth = CGFloat(0.0)
var borderColor: UIColor?
override func layoutSubviews()
super.layoutSubviews()
// don't apply mask if corners is not set, or if radius is Zero
guard let _corners = corners, radius > 0.0 else
return
roundCorners(corners: _corners, radius: radius, borderWidth: borderWidth, borderColor: borderColor)
这给您带来了一些好处:1) 它会在按钮框架发生变化时更新其遮罩层框架(例如,旋转设备),以及 2) 您可以从自定义单元类 中设置这些值或来自 cellForRowAt。
无论哪种方式,将您的 btnStatus
类从 UIButton
更改为 RoundedButton
- 在您的故事板和 @IBOutlet
连接中。
然后将您的 CustomTableViewCell
更改为:
class CustomTableViewCell: UITableViewCell
@IBOutlet weak var btnStatus: RoundedButton!
override func awakeFromNib()
super.awakeFromNib()
// set up corner maskign
btnStatus.corners = .bottomRight
btnStatus.radius = 7.0
// set if desired
// btnStatus.borderWidth = 2.0
// btnStatus.borderColor = .blue
override func setSelected(_ selected: Bool, animated: Bool)
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
最后,您的cellForRowAt
函数变为:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = self.tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomTableViewCell
return cell
应该可以的...
【讨论】:
像魅力一样工作!【参考方案2】:我查看了您的代码。问题是您的roundCorners
函数取决于您的视图边界来设置图层的属性,并且您在awakeFromNib
中调用roundCorners
,此时您的单元格具有与NIB 文件中相同的边界,因为自动布局尚未还算算。您需要将您的 roundCorners
调用移动到 layoutSubviews
,以便在自动布局计算完您的边界后调用它。
import UIKit
class CustomTableViewCell: UITableViewCell
@IBOutlet weak var btnStatus: UIButton!
override func layoutSubviews()
super.layoutSubviews()
self.btnStatus.roundCorners(corners: [.bottomRight], radius: 7.0, borderWidth: nil, borderColor: nil)
EDIT 还将 cell.setNeedsLayout() 添加到 cellforRowAt 以强制在第一次绘制单元格之前调用 layoutSubviews。
【讨论】:
同样的问题 :( 我正在运行它并且它正在工作。您是否正确移动了代码? 是的,哪个模拟器,我在iphone7,ios11中检查,如果你能上传zip就好了,我就跑比较一下 它在 iphone 7 iOS11 上是正确的。查看整个文件的编辑答案。 在真实设备上也是如此,实际上如果我滚动它可以解决问题,但前提是再次渲染单元格【参考方案3】:也许你的按钮是重叠的,因为它没有上限?尝试添加一个明亮的边框,看看您是否可以看到顶部,如果没有,请尝试在顶部添加一个约束。另外,不要给它一个静态高度,而是尝试让它与其上方的对象成比例的高度(可能是您设备的屏幕尺寸导致它重叠)
【讨论】:
dropbox.com/sh/751wo3hsesjxj6l/AAA3oJyPSVFQ3PZcvRTRPE-Sa?dl=0 没有帮助以上是关于Swift:按钮圆角打破约束的主要内容,如果未能解决你的问题,请参考以下文章