我有一个TableViewCell和两个按钮来切换不同的约束。
我要更新它的高度限制和像元高度。
就像下面的pic1
当我单击buttonB时,视图将像pic2一样更改
然后单击buttonA,视图将返回到pic1
我尝试修改约束,但无法更新高度。
对我有任何想法或答案吗?
谢谢
pic1
pic2
这里是代码:
class CellContainView: UIView {
let buttonA: UIButton = { () -> UIButton in
let ui = UIButton()
ui.titleLabel?.numberOfLines = 0
ui.setTitle("Click\nA", for: .normal)
ui.backgroundColor = UIColor.blue
return ui
}()
let buttonB: UIButton = { () -> UIButton in
let ui = UIButton()
ui.titleLabel?.numberOfLines = 0
ui.setTitle("Click\nB", for: .normal)
ui.backgroundColor = UIColor.gray
return ui
}()
let buttonC: UIButton = { () -> UIButton in
let ui = UIButton()
ui.titleLabel?.numberOfLines = 0
ui.setTitle("Click\nC", for: .normal)
ui.backgroundColor = UIColor.brown
return ui
}()
let labelA: UILabel = { () -> UILabel in
let ui = UILabel()
ui.text = "Test"
return ui
}()
let viewA: UIView = { () -> UIView in
let ui = UIView()
ui.backgroundColor = UIColor.red
return ui
}()
override init(frame: CGRect) {
super.init(frame: frame)
addUI()
addConstrain()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func addUI() {
self.addSubview(buttonA)
self.addSubview(buttonB)
self.addSubview(buttonC)
self.addSubview(labelA)
self.addSubview(viewA)
}
func addConstrain() {
buttonA.snp.makeConstraints { (make) in
make.left.top.equalToSuperview()
make.height.equalTo(60)
}
buttonB.snp.makeConstraints { (make) in
make.left.equalTo(buttonA.snp.right)
make.top.right.equalToSuperview()
make.width.equalTo(buttonA.snp.width)
make.height.equalTo(buttonA.snp.height)
}
buttonC.snp.makeConstraints { (make) in
make.left.equalTo(15)
make.right.equalTo(-15)
make.bottom.equalTo(-15)
make.height.equalTo(50)
}
labelA.snp.makeConstraints { (make) in
make.left.equalTo(15)
make.top.equalTo(buttonA.snp.bottom).offset(15)
make.width.equalTo(195)
make.height.equalTo(50)
}
viewA.snp.makeConstraints { (make) in
make.left.equalTo(labelA.snp.right)
make.top.equalTo(buttonA.snp.bottom).offset(15)
make.right.equalTo(-15)
make.height.equalTo(50)
make.bottom.equalTo(buttonC.snp.top).offset(-10)
}
}
func updateConstrain(sender: UIButton) {
switch sender {
case buttonA:
viewA.snp.updateConstraints { (make) in
make.height.equalTo(50)
}
case buttonB:
viewA.snp.updateConstraints { (make) in
make.height.equalTo(150)
}
default:
break
}
}
}
class TestTableViewCell: UITableViewCell {
let cellContainView: CellContainView = { () -> CellContainView in
let ui = CellContainView()
ui.backgroundColor = UIColor.orange
return ui
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.addSubview(cellContainView)
cellContainView.snp.makeConstraints { (make) in
make.left.top.equalTo(15)
make.bottom.right.equalTo(-15)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let tableView: UITableView = { () -> UITableView in
let ui = UITableView()
return ui
}()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
tableView.register(TestTableViewCell.self, forCellReuseIdentifier: "TestTableViewCell")
tableView.tableFooterView = UIView()
self.view.addSubview(tableView)
tableView.snp.makeConstraints { (make) in
make.top.left.right.bottom.equalToSuperview()
}
}
@objc func buttonAClicked(sender: UIButton) {
let index = IndexPath(row: 0, section: 0)
let cell = tableView.cellForRow(at: index) as! TestTableViewCell
cell.cellContainView.updateConstrain(sender: sender)
tableview.reloadData()
}
@objc func buttonBClicked(sender: UIButton) {
let index = IndexPath(row: 0, section: 0)
let cell = tableView.cellForRow(at: index) as! TestTableViewCell
cell.cellContainView.updateConstrain(sender: sender)
tableview.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCell", for: indexPath) as! TestTableViewCell
cell.cellContainView.buttonA.addTarget(self, action: #selector(buttonAClicked), for: .touchUpInside)
cell.cellContainView.buttonB.addTarget(self, action: #selector(buttonBClicked), for: .touchUpInside)
return cell
}
}
当我单击butttonB时更新约束问题(添加更新viewA heightConstrain和tableview.reloadData()):
TestCellUpdateHeight[29975:5195310] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<SnapKit.LayoutConstraint:0x6040000a4320@CellContainView.swift#75 UIButton:0x7fa1d0d0d680.height == 60.0>",
"<SnapKit.LayoutConstraint:0x6040000a49e0@CellContainView.swift#89 UIButton:0x7fa1d0d10610.height == 50.0>",
"<SnapKit.LayoutConstraint:0x6040000a51c0@CellContainView.swift#104 UIView:0x7fa1d0d11130.height == 150.0>",
"<SnapKit.LayoutConstraint:0x6040000a4800@CellContainView.swift#80 UIButton:0x7fa1d0d0f7b0.top == TestCellUpdateHeight.CellContainView:0x7fa1d0d0d470.top>",
"<SnapKit.LayoutConstraint:0x6040000a4a40@CellContainView.swift#82 UIButton:0x7fa1d0d0f7b0.height == UIButton:0x7fa1d0d0d680.height>",
"<SnapKit.LayoutConstraint:0x6040000a4ec0@CellContainView.swift#88 UIButton:0x7fa1d0d10610.bottom == TestCellUpdateHeight.CellContainView:0x7fa1d0d0d470.bottom - 15.0>",
"<SnapKit.LayoutConstraint:0x6040000a5100@CellContainView.swift#102 UIView:0x7fa1d0d11130.top == UIButton:0x7fa1d0d0f7b0.bottom + 15.0>",
"<SnapKit.LayoutConstraint:0x6040000a5220@CellContainView.swift#105 UIView:0x7fa1d0d11130.bottom == UIButton:0x7fa1d0d10610.top - 10.0>",
"<SnapKit.LayoutConstraint:0x6040000a52e0@TestTableViewCell.swift#26 TestCellUpdateHeight.CellContainView:0x7fa1d0d0d470.top == TestCellUpdateHeight.TestTableViewCell:0x7fa1d208a000.top + 15.0>",
"<SnapKit.LayoutConstraint:0x6040000a53a0@TestTableViewCell.swift#27 TestCellUpdateHeight.CellContainView:0x7fa1d0d0d470.bottom == TestCellUpdateHeight.TestTableViewCell:0x7fa1d208a000.bottom - 15.0>",
"<NSLayoutConstraint:0x6080002819f0 'UIView-Encapsulated-Layout-Height' TestCellUpdateHeight.TestTableViewCell:0x7fa1d208a000'TestTableViewCell'.height == 230 (active)>"
)
Will attempt to recover by breaking constraint
答案 0 :(得分:4)
通常,要更新uiview:UIView
的高度约束,应先保存它:
var viewHeightConstraint: Constraint!
uiview.snp.makeConstraints { (make) in
viewHeightConstraint = make.height.equalTo(50).constraint
}
如果仅使用updateConstraints
函数,它将添加一个新的高度约束,从而导致问题Unable to simultaneously satisfy constraints
。因此,您必须删除最后一个:
viewHeightConstraint.deactivate()
然后再次进行约束:
uiview.snp.makeConstraints { (make) in
viewHeightConstraint = make.height.equalTo(100).constraint
}
答案 1 :(得分:0)
您目前正在做什么
labelA.snp.updateConstraints { (make) in
make.bottom.equalTo(buttonC.snp.top).offset(-100)
}
将增加labelA的底部距离,但将其顶部常量保留为您需要的相同值
1-更新labelA
或
2-更新RedView前面的高度
也别忘了打电话
cell.cellContainView.updateConstrain(sender: sender)
cell.layoutIfNeeded()
还请注意,由于单元格的重用,您可能会发现其他单元格被拉伸,因此您需要跟踪拉伸的单元格索引,并将其应用于cellForRowAt
您也可以这样做
func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat
return expandArr[indexPath.row] ? 300 : 100
}
其中
var expandArr = [Bool]()
指示单元格是否已扩展,如果您有模型,也可以在其中添加bool值,而不是单独的arr(用于说明)
答案 2 :(得分:0)
您不能仅通过更改其约束来更新其高度。
由于reloadData()
的调用,表格只能更新其单元格的高度,此后它将向其delegate
询问单元格的高度(如果您的单元格是自动调整大小,则自动计算)
因此,要获得想要的效果,您可以执行以下操作。
在buttonBClicked
方法中,记住要获取的状态(可能使用一些变量)。
在表委托人的方法tableView(_:, heightForRowAt:)
中返回单元格的正确高度。
这不是理想的选择,只是作为考虑您的解决方案的指导。我的主要观点是,您需要重新加载表格视图以更改单元格的高度。
答案 3 :(得分:0)
如果您需要重新计算高度单元格(而无需重新创建单元格/重新加载单元格),只需调用:
tableView.beginUpdates()
tableView.endUpdates()
答案 4 :(得分:0)
我认为您不需要更改“底部约束”。您需要的是将“高度约束”应用于redView。并根据“选择”按钮进行更改。
func updateConstrain(sender: UIButton) {
switch sender {
case buttonA:
redView.snp.updateConstraints { (make) in
make.heigh.equalTo(10)
}
case buttonB:
redView.snp.updateConstraints { (make) in
make.heigh.equalTo(100)
}
default:
break
}
}
}
别忘了在更新约束后重新加载特定行
@objc func buttonAClicked(sender: UIButton) {
let index = IndexPath(row: 0, section: 0)
let cell = tableView.cellForRow(at: index) as! TestTableViewCell
cell.cellContainView.updateConstrain(sender: sender)
yourtableview.reloadRows(at: [IndexPath(row: 0, section: 0)], with: UITableViewRowAnimation.none)
}
@objc func buttonBClicked(sender: UIButton) {
let index = IndexPath(row: 0, section: 0)
let cell = tableView.cellForRow(at: index) as! TestTableViewCell
cell.cellContainView.updateConstrain(sender: sender)
yourtableview.reloadRows(at: [IndexPath(row: 0, section: 0)], with: UITableViewRowAnimation.none)
}