在自动布局中动态地将视图移动到新位置

3

我有一个自定义的UITableViewCell布局,看起来像这样。它有三个标签。

enter image description here

标签2是可选的。它不在每个单元格中都存在。因此,当发生这种情况时,我想隐藏它并将标签1下移一点,使其与标签3居中对齐。

enter image description here

Here are the constraints I've added for each label. 以下是我为每个标签添加的约束条件。
Label 1 标签1

enter image description here

标签2

enter image description here

标签 3

enter image description here

注意,我添加了一个额外的约束条件,将Y轴与标签1对齐,值为0,并将其优先级设置为750。我认为如果我删除标签2,那个优先级较低的约束条件就会取代它并向下移动。
class TableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    // MARK: - Table view data source
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell

        if indexPath.row == 1 {
            cell.label2.removeFromSuperview()
            cell.updateConstraints()
        }

        return cell
    }
}

但似乎没有起作用。 标签2 被移除了,但是 标签1 的位置仍然不变。

enter image description here

我如何实现我想要的?


尝试 #1

根据 T 先生在下方的 answer,我给 标签 1 添加了一个顶部约束。然后在 cellForRowAtIndexPath 方法中,我改变了它的值。

override func tableView(tableView: UITableView, cellForRowAtIndexPath 

    indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell

        if indexPath.row == 1 {
            cell.label2.removeFromSuperview()
            cell.topConstraint.constant = cell.bounds.height / 2
            cell.layoutIfNeeded()
        }

        return cell
    }

但这也不起作用。

尝试使用 layoutIfNeeded 吗? - zc246
@zcui93 刚刚试过了,没有任何变化。 - Isuru
我注意到标签1的CentreY约束都针对于superview,第二个约束应该与标签2有关吗? - zc246
尝试使用cell.contentView layoutIfNeeded。 - Teja Nandamuri
还可以尝试调用cell的updateConstraintsIfNeeded方法。 - Teja Nandamuri
显示剩余3条评论
3个回答

0
我想到了一种方法来利用NSLayoutConstraint的新active属性来完成这个,如answer中所述。
我使用IBOutlet创建了一个与值为-13的Align center Y约束。我删除了其中的weak关键字。
然后在cellForRowAtIndexPath方法中,我只是切换active属性的值。
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell

    if indexPath.row % 2 == 0 {
        cell.label2.hidden = true
        cell.oldConstraint.active = false
    } else {
        cell.label2.hidden = false
        cell.oldConstraint.active = true
    }

    return cell
}

enter image description here


我仍然不认为这是一个最好的解决方案。由于标签具有固有大小,应该有一种方法只通过将标签文本设置为nil来实现这一点。明天会检查并给出答案。 - Zell B.

0
尝试为标签1的顶部约束设置出口。当您删除标签2时,请更新标签1的顶部约束,该约束为container.height/2。或者,删除顶部约束并将centerY约束赋予标签1。如果需要,请进行布局,一旦您更新了约束条件。

刚试了一下,但不幸的是似乎不起作用。 - Isuru
更新了问题。 - Isuru

0

我非常欣赏你所走过的路程,如果我要完成这个任务,我会完全按照你的步骤来做 :)

现在我的建议是: 删除一个多余的“将中心与值为0的标签1对齐”的设置,因为它没有任何作用 :)

我可以看到你已经有了一个将标签1与y轴居中的设置,我相信是-13。为此创建一个iboutlet吧 :) 假设它的名称为centerLabel1Constraint :)

每当你想将标签1居中时,隐藏标签2并设置centerLabel1Constraint.constant = 0,然后调用[cell layoutIfNeeded]

那应该就可以了 :) 祝编码愉快 :)


谢谢回复。我尝试了这个方法。它可以工作,但只有部分地。问题在于,对于那些具有标签2的单元格,没有办法确定常量的值,因为一旦将其设置为0,在单元格被重用时它就会被重新使用。 - Isuru
你已经知道这个常量的值了吧?我的意思是,当你想要显示label2时,只需将其设置为可见,并将centerLabel1Constraint.constant的值设回-13,然后调用[cell layoutIfNeeded]。 - Sandeep Bhandari
总之,你的cellForRow at indexPath看起来像这样:if(condition:show label2){centerLabel1Constraint.constant=-13; label2.Hidden=NO; [cell layoutIfNeeded]} else{{centerLabel1Constraint.constant=0;label2.Hidden=YES; [cell layoutIfNeeded]} 对吧??? :) - Sandeep Bhandari
事实上,我不太舒服硬编码数值-13。因为这些单元格是自动调整大小的。无论如何,我找到了一种方法来解决这个问题。我在下面发布了它(https://dev59.com/H5Lea4cB1Zd3GeqP01RR#34421192)。感谢您的帮助。 - Isuru
硬编码-13不会有任何影响,因为它总是从中心减去y值,该值根据单元格的高度动态计算。所以无论单元格的大小如何,它始终会显示在垂直居中线上方13像素的位置。这就是苹果提供该常量概念的目的。无论如何,很高兴你找到了解决方案 :) - Sandeep Bhandari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接