简体   繁体   中英

Layout changes after selecting cell in tableView

I have a normal Table View with cells that get configured with this code:

override function tableView(...cellForRowAt indexPath: IndexPath) {
    let cell = tableView.dequeueReusableCell(myIdentifier) as CellClass

    cell.title.text = "this is a title"

    descriptionLabel = UILabel()
    descriptionLabel.numberOfLines = 0
    descriptionLabel.text = "this is a description"

    cell.accessoryView = UISwitch()

    // layout constraints
    leadingSpaceToSuperviewFor(cell.title)
    topSpaceToSuperviewFor(cell.title)
    bottomSpaceTo(view: label, from: cell.title) 

    leadingSpaceToSuperviewFor(label)
    toSpaceTo(view: cell.title, from: label)
    bottomSpaceToSuperviewFor(label)
}

func leadingSpaceToSuperviewFor (view: UILabel ) {
    if let superview = view.superview{
        let constraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-[view]", options: [], metrics: [:], views: ["view": view])
        constraints.forEach({ $0.priority = UILayoutPriorityRequired })
        superview.addConstraints(constraints)
    }
}

func topSpaceToSuperviewFor (view: UILabel) {
    // same as above but with this constraint
    let constraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-[view]", options: [], metrics: [:], views: ["view": view])
}

func bottomSpaceToSuperviewFor (view: UILabel) {
    // same as above but with constraint
    let constraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[view]-|", options: [], metrics: [:], views: ["view": view])
}

// other constraint functions follow the same pattern.

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { //do nothing }

The code builds and I get a nice looking table. My problem is that the cell's title loses its constraint when I click on the cell, even though the didSelectRowAt function does nothing.

This is how the table looks like at the beginning: 建好后的桌子

This is how it looks right after I tap on the bottom cell: 轻触单元格后的表格

As you can see, the bottom constraint of the title just disappears. I do not get any constraint conflicts in the console.

Even more curious is the fact that, if I press a cell, that one and the one above will have this problem, but not any other one in the table.

Also, if I just press the switch, it toggles accordingly without affecting the layout.

Any ideas on what could be making the constraint change after clicking on a cell?

UPDATE 1:

  • There is not .xib file for this, it is a requirement that it is solved only programmatically.

  • There are no other constraints than the one mentioned above.

I guess this is due to some missing constraints. Like for title label, you're only setting it's Leading , Top and Bottom try by setting constraints for height and width which seems missing.

Also, I don't think that debugger will show any errors in the console for missing constraints if you're not using storyboard then for missing constraints we only have to analyze this visually, however, in the console, we only got the conflicting constraints information.

Detail

For setting constraint on each element (view, label, image etc) two things are required:

  1. Element position
  2. Element size

1.Element position: In order to set an element position you need to specify at-least two constraints ie for its x-position (horizontal space from origin) and for y-position (vertical space from origin).

_____________________________________________________________
|                              |
|                              |
|                         Top constraint
|                              |
|                              |
|---Leading constraint----[ Label ]
|
|

It depends on view presentation, we can set leading and top or we can set horizontally in a container and vertically in the container to make a view in center align.

2. Element size: For element's size, [i] we need to set its width and height constraint.

_______________________________________________________________________
|                                  |                            
|                                  |                            
|                             Top constraint                            
|                                  |                            ^
|                                  |                            |
|---Leading constraint----[       Label          ]            Height
|                                                           constraint
|                          <---Width costraint--->              |
|                                                               ^
|

Again its depends on presentation that how much size of an element should be like if it's with is not fixed and should be from screen's edge to edge then rather applying fixed width constraint we need to set width equal to its super view or we can only set Leading and Trailing constraint to satisfy it's width constraint.

To know more about setting constraints programmatically check out the Apple's VFL explanation (Visual Format Language)

Good Tutorial: https://www.raywenderlich.com/110393/auto-layout-visual-format-language-tutorial

I added a height and a width like NSIceCode suggested, but that did not work. This did the job:

tableView(...cellForRowAt ...) {
    let cell = (tableView.dequeueReusableCell(myId) as? CellClass) ??
        CellClass(style: .subtitle, reuseIdentifier: myId)
}

On top of that, I added trailing constraints to the switch:

tableView (...) {
   ...
   trailingSpaceToSuperviewFor(switchControl)
   topSpaceToSuperviewFor(switchControl)
   bottomSpaceToSuperviewFor(switchControl)
   trailingSpaceTo(switchControl, from: cell.title)
   trailingSpaceTo(switchControl, from: cell.detailTextLabel)
}

Cell's height was 44, the default one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM