如何显示隐藏的UIButton?布局约束冲突致宽度无法刷新
解决约束冲突与按钮宽度不刷新问题
你的问题核心在于重复添加宽度约束,以及没有正确管理约束的激活状态,导致布局引擎无法同时满足多个冲突的宽度限制,同时按钮宽度也不会按预期更新。下面一步步帮你修复:
问题分析
在setupLayout里,你给imgButton添加了一个宽度为0的约束:
imgButton.widthAnchor.constraint(equalTo: imgButton.heightAnchor, multiplier: 0).isActive = true
然后点击按钮时,又添加了新的宽度约束(equalToConstant:50或0),但旧的约束并没有被禁用。这就导致两个宽度约束同时生效,触发了约束冲突。另外,直接调用updateConstraints()并不是正确的更新约束方式,布局引擎需要的是修改现有约束的属性或者切换约束的激活状态。
修复方案
1. 存储宽度约束为实例变量
首先,把imgButton的宽度约束存为一个实例变量,这样后续可以直接修改它的constant值,而不用每次添加新约束。
修改你的类属性:
// 替换原来的var imgViewWidth: NSLayoutConstraint! var imgButtonWidthConstraint: NSLayoutConstraint!
2. 初始化时设置基础宽度约束
在setupLayout里,初始化这个宽度约束并激活它,初始宽度设为0:
// 替换原来的imgButton.widthAnchor.constraint(equalTo: imgButton.heightAnchor, multiplier: 0).isActive = true imgButtonWidthConstraint = imgButton.widthAnchor.constraint(equalToConstant: 0) imgButtonWidthConstraint.isActive = true
3. 修改按钮点击事件的逻辑
在点击事件里,只需要修改约束的constant值,同时控制按钮的隐藏状态(或者可以通过宽度为0来实现隐藏,不用isHidden,看你需求):
@objc func addBtnAction(_ sender: UIButton){ print("hi") if trashIsSelected == false{ trashIsSelected = true imgButton.isHidden = false imgButtonWidthConstraint.constant = 50 }else{ trashIsSelected = false imgButtonWidthConstraint.constant = 0 // 可选:如果希望宽度为0时完全隐藏,也可以保留isHidden,或者只靠宽度为0实现隐藏 imgButton.isHidden = true } // 触发布局更新,带动画更流畅 UIView.animate(withDuration: 0.2) { self.view.layoutIfNeeded() } }
额外优化建议
- 可以去掉
isHidden,直接通过宽度为0来实现按钮的隐藏效果,这样更符合AutoLayout的逻辑,避免状态不一致。 - 使用
NSLayoutConstraint.activate()批量激活约束,让代码更整洁易读。
完整修改后的代码片段
import UIKit class MainViewController: UIViewController { var trashIsSelected: Bool! let imgButton: UIButton = { let imgView = UIButton() imgView.setImage(UIImage(named: "schedule_delete_icon"), for: .normal) imgView.translatesAutoresizingMaskIntoConstraints = false return imgView }() let deleteButton: UIButton = { let imgBtn = UIButton() imgBtn.setImage(UIImage(named: "icon_delete"), for: .normal) imgBtn.translatesAutoresizingMaskIntoConstraints = false return imgBtn }() let label: UILabel = { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.text = "하ㅣㅇ하이히아히아하하하하ㅏㅎ하ㅏㅎ하ㅏ하하하하ㅏㅏ하하하하하ㅏ" return label }() // 存储宽度约束 var imgButtonWidthConstraint: NSLayoutConstraint! override func viewDidLoad() { super.viewDidLoad() setupLayout() } func setupLayout(){ let testView = UIScrollView() self.view.addSubview(testView) testView.backgroundColor = .lightGray testView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ testView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), testView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), testView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor), testView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.3) ]) testView.addSubview(imgButton) testView.addSubview(label) NSLayoutConstraint.activate([ imgButton.leadingAnchor.constraint(equalTo: testView.leadingAnchor, constant: 10), imgButton.centerYAnchor.constraint(equalTo: testView.centerYAnchor), imgButton.heightAnchor.constraint(equalTo: testView.heightAnchor, multiplier: 0.2) ]) // 初始化宽度约束 imgButtonWidthConstraint = imgButton.widthAnchor.constraint(equalToConstant: 0) imgButtonWidthConstraint.isActive = true imgButton.isHidden = true trashIsSelected = false NSLayoutConstraint.activate([ label.centerYAnchor.constraint(equalTo: testView.centerYAnchor), label.leadingAnchor.constraint(equalTo: imgButton.trailingAnchor, constant: 10), label.heightAnchor.constraint(equalTo: testView.heightAnchor, multiplier: 0.2), label.widthAnchor.constraint(equalTo: testView.widthAnchor, multiplier: 0.5) ]) self.view.addSubview(deleteButton) NSLayoutConstraint.activate([ deleteButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), deleteButton.bottomAnchor.constraint(equalTo: self.view.bottomAnchor) ]) deleteButton.addTarget(self, action: #selector(addBtnAction(_:)), for: .touchUpInside) } @objc func addBtnAction(_ sender: UIButton){ print("hi") if !trashIsSelected { trashIsSelected = true imgButton.isHidden = false imgButtonWidthConstraint.constant = 50 } else { trashIsSelected = false imgButtonWidthConstraint.constant = 0 imgButton.isHidden = true } // 带动画更新布局 UIView.animate(withDuration: 0.2) { self.view.layoutIfNeeded() } } }
这样修改后,你就不会再遇到约束冲突,而且imgButton的宽度会正确刷新,点击按钮时的切换效果也更流畅。
内容的提问来源于stack exchange,提问作者hoyeong kim
相关产品推荐
相关产品推荐

