Isuru
Isuru

Reputation: 31283

Dynamically move a view to a new position in auto layout

I have a custom UITableViewCell layout that looks like this. It has three labels.

enter image description here

Label 2 is an optional one. It's not present in every cell. So I want to hide that and move the Label 1 down a little to be center aligned with the Label 3 when that happens.

enter image description here

Here are the constraints I've added for each label.

Label 1

enter image description here

Label 2

enter image description here

Label 3

enter image description here

Notice I have added an extra constraint, Align center to Y with the value of 0 to Label 1 and have set its priority to 750. I figured if I remove the Label 2, that constraint with the lower priority will take its place and move down.

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
    }
}

But it doesn't seem to work. Label 2 is removed but Label 1's position is still the same.

enter image description here

How can I accomplish what I'm after?


Attempt #1

As per Mr. T's answer below, I added a top constraint to the Label 1. And then in the cellForRowAtIndexPath method, I changed it's value.

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
    }

But this didn't work either.

Upvotes: 3

Views: 1606

Answers (3)

Isuru
Isuru

Reputation: 31283

I figured out a way to do this utilizing the new active property of NSLayoutConstraints as described in this answer.

I made an IBOutlet to the Align center Y constraint with the value -13. Removed the weak keyword from it.

Then in the cellForRowAtIndexPath method, I'm simply toggling the value for the active property.

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

Upvotes: 0

Sandeep Bhandari
Sandeep Bhandari

Reputation: 20379

I am pretty much impressed the way you came so far as that would have been exactly the same steps i would have followed if i had to accomplish it :)

Now my suggestion: remove an extra "Align center to Y with the value of 0 to Label 1" that you have added that is not serving any purpose :)

I can see you already have a align center to y with some offset i believe -13 to label 1. Create an iboutlet for that :) let's say its name as centerLabel1Constraint :)

whenever you want to bring label 1 to center hide label 2 and set centerLabel1Constraint.constant = 0 and call [cell layoutIfNeeded]

That should do the job :) Happy coding :)

Upvotes: 0

Teja Nandamuri
Teja Nandamuri

Reputation: 11201

Try to have an outlet for the top constraint for the label 1. And when you remove the label 2, update the top constraint for the label1 which is the container.height/2 Or Remove the top constraint and give the centerY constraint to the label 1. And do layout if needed, once you updated the constraints.

Upvotes: 0

Related Questions