Clueless G
Clueless G

Reputation: 13

UITableViewCell height does not auto adjust (and instead squashed my UIView) when I try to add a UIView programmatically

Environment ... Swift 4.0, iOS 11.0+

Newbie in Swift and apple development here .. I am trying to add a UIView (of varying height) to a UITableViewCell. The UIView appears to be added correctly but the UITableViewCell is not adjusting its height to show the entire UIView.

Came across this: https://stackoverflow.com/a/36422189/3681880. I tried to go back to basics by creating this specific example from scratch to ensure the cell row heights are adjusting according to the label size. This works for me as expected.

Next step, I tried to add a UIImageView into the MyCustomCell implementation and this is where my problem is...

class MyCustomCell: UITableViewCell {

    @IBOutlet weak var myCellLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()

        let imageView = UIImageView(frame: CGRect(x:0.0,y:0.0,width:100.0,height:100.0))
        imageView.image = UIImage(named:"addData_20pt")

        contentView.addSubview(imageView)

        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.topAnchor.constraint(equalTo: self.topAnchor, constant: 20).isActive = true
        imageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10).isActive = true
        imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -10).isActive = true
    }
}

In the screenshot, you can see that the images are all squashed to fit into the top rows. How do I get the cells to expand to fit the images instead?

ugly screenshot of tableview now

(Apologies for the really ugly table - have just thrown that together to understand the concept!)

For quick reference, this is the ViewController code from the post referenced above

import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    // These strings will be the data for the table view cells
    let animals: [String] = [
        "Ten horses:  horse horse horse horse horse horse horse horse horse horse ",
        "Three cows:  cow, cow, cow",
        "One camel:  camel",
        "Ninety-nine sheep:  sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep baaaa sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep",
        "Thirty goats:  goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat "]

    // Don't forget to enter this in IB also
    let cellReuseIdentifier = "cell"

    @IBOutlet var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // delegate and data source
        tableView.delegate = self
        tableView.dataSource = self

        // Along with auto layout, these are the keys for enabling variable cell height
        tableView.estimatedRowHeight = 44.0
        tableView.rowHeight = UITableViewAutomaticDimension
    }

    // number of rows in table view
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.animals.count
    }

    // create a cell for each table view row
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell:MyCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MyCustomCell
        cell.myCellLabel.text = self.animals[indexPath.row]
        return cell
    }

    // method to run when table view cell is tapped
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("You tapped cell number \(indexPath.row).")
    }
}

Upvotes: 0

Views: 685

Answers (2)

Clueless G
Clueless G

Reputation: 13

Adding this as an answer for completion ...

With help from Sergey's answer, I managed to get this done in both the storyboard and programmatically. Most important bit was playing around with the "greater than or equal to" constraint. Thanks Sergey!

another ugly tableview screenshot with cell row height adjusted

class MyCustomCell: UITableViewCell {

    @IBOutlet weak var myCellLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        let myView = UIImageView()
        myView.image = UIImage(named:"addData_20pt")
        contentView.addSubview(myView)
        myView.backgroundColor = UIColor.red
        myView.translatesAutoresizingMaskIntoConstraints = false
        myView.topAnchor.constraint(equalTo: myCellLabel.bottomAnchor, constant: 20).isActive = true
        myView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        myView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
        myView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
        myView.heightAnchor.constraint(greaterThanOrEqualToConstant: 100.0).isActive = true

    }
}

Upvotes: 1

Sergey Polozov
Sergey Polozov

Reputation: 235

So you have set your cells' size only with your label. I don't know how do you wanna see your cells but if you want your cells' size to change according to label or imageView then I would advise you to do the following:

1)set your imageView in XIB instead of code

2)set constraints like that:

enter image description here

enter image description here

Your image you can set in XIB or:

imageView.image = UIIMage(named: "YourImageName")

My solution looks like that:

enter image description here

Or you can arrange it how you want, play with imageView's property "grater of equal"

Upvotes: 2

Related Questions