仅设置UIButton左下角圆角时按钮消失的问题排查
这问题我太熟了!你的按钮之所以消失,核心原因是调用roundBtnCorners方法时,按钮的布局还没完成——此时self.bounds还是空的(CGRectZero),导致你创建的遮罩层(CAShapeLayer)没有实际尺寸,直接把整个按钮都遮罩掉了,自然就看不到了。
问题根源拆解
你现在的代码是先调用roundBtnCorners,再添加约束布局,但约束的生效是异步的,在调用方法的瞬间,按钮的bounds还没根据约束计算出来,贝塞尔路径基于空的bounds创建,遮罩层也就没有任何显示区域。
三种可行的解决方案
方案1:用iOS 11+原生API直接设置(最推荐)
苹果在iOS 11之后给CALayer新增了maskedCorners属性,不需要自己写贝塞尔路径,简单又不会踩布局的坑:
cancelBtn.setTitle("Cancel", for: .normal) cancelBtn.setTitleColor(UIColor.ecaftRed, for: .normal) cancelBtn.layer.borderWidth = 3 cancelBtn.layer.borderColor = UIColor.whiteFadedPlus.cgColor // 直接用原生API设置左下角圆角 cancelBtn.layer.cornerRadius = 25 cancelBtn.layer.maskedCorners = [.layerMinXMaxYCorner] // 对应UIRectCorner.bottomLeft cancelBtn.addTarget(self, action: #selector(cancelBtnTapped(_:)), for: .touchUpInside) popUpView.addSubview(cancelBtn) cancelBtn.snp.makeConstraints { (make) -> Void in make.left.equalTo(popUpView) make.bottom.equalTo(popUpView) make.size.equalTo(CGSize(width: 0.5*popUpView.frame.width, height: 0.25*popUpView.frame.height)) }
这种方式会自动跟随按钮的布局变化更新圆角,完全不需要担心bounds的问题。
方案2:修改你的扩展方法,让它适配布局变化
如果需要兼容iOS 11以下版本,可以修改roundBtnCorners方法,让遮罩层能跟随按钮的bounds自动调整:
extension UIButton{ func roundBtnCorners(_ corners:UIRectCorner, radius: CGFloat){ // 先移除旧的遮罩,避免重复添加导致的问题 self.layer.mask = nil let maskLayer = CAShapeLayer() // 用当前的bounds创建路径 let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)) maskLayer.path = path.cgPath // 设置遮罩层的自动调整属性,跟随按钮尺寸变化 maskLayer.autoresizingMask = [.layerWidthSizable, .layerHeightSizable] maskLayer.frame = self.bounds self.layer.mask = maskLayer } }
然后记得在布局完成后调用这个方法,比如把roundBtnCorners的调用放到viewDidLayoutSubviews里:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() cancelBtn.roundBtnCorners([.bottomLeft], radius: 25) }
方案3:强制布局后再设置圆角
在添加约束后,强制让按钮完成布局,再调用圆角方法:
cancelBtn.snp.makeConstraints { (make) -> Void in make.left.equalTo(popUpView) make.bottom.equalTo(popUpView) make.size.equalTo(CGSize(width: 0.5*popUpView.frame.width, height: 0.25*popUpView.frame.height)) } // 强制触发布局计算 popUpView.layoutIfNeeded() // 此时按钮的bounds已经正确,再设置圆角 cancelBtn.roundBtnCorners([.bottomLeft], radius: 25)
总结
最推荐方案1,原生API不仅简洁,还能避免手动处理布局同步的问题。如果必须兼容低版本,方案2或3都能解决按钮消失的问题——核心思路就是确保在按钮的bounds已经确定后,再创建遮罩层。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

