Resizing a UIImageView inside a UITableViewCell to fit the table width

I’ve been banging my head on this one. Perhaps someone can point me in the right direction.

I want to have a tablefield where the cells hold images. The images may be of different sizes, but I want the images to fill the width of the tableview and for the height of the row to be large enough to show the image in it’s original aspect ratio.

I have resized the tableviewcell so the height is correct, but all of my attempts to resize the imageview (by setting the frame and/or bounds) cause it to be too big within the tableviewcell.

If anyone knows of a working example, I’d like to see it!

I’m using Swift, but Obj-c is fine.

Thanks.

You can use auto layout for this. Add constraints to the UIImageView so its top, bottom, leading and trailing edges are the same of the UITableViewCell. The cell’s width and the image’s dimensions will then determine the height of the cell.

The table view still needs to know that its cells are generating their own heights; you can do this in code.

	tableView.rowHeight = UITableViewAutomaticDimension
	tableView.estimatedRowHeight = 117

117 in the above example doesn’t have to be an accurate value; the table view will use it as part of its layout calculations until the constraints take over. I think it does need to be greater than 0, though.

I’m assuming for this that the image occupies the entire cell and all of the cells in the table use autolayout.

1 Like

Thanks for the suggestion, but yes, I was already doing that, but something very odd is going on.

I haven’t found one example online of what I’m attempting to do.

I have a webview in a table cell and that behaves impeccably.

Just an update. Almost got it working…

It seems I was setting the setting the cell height to be the image height, rather than the height adjusted to match the image aspect ratio and tablefield width.

I still have an odd displacement of the leading edge, I guess I’ll work out where that is coming from…

Thanks for your assistance, although I was already doing those things, it was helpful to show I was on the right track.

Paul

For anyone interested, here’s the code -

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    ... code removed here ...

            switch  thisContent.contentType {
                
            case .Video: // This cell will just show a thumbnail image
                let videoThumbCell = tableView.dequeueReusableCellWithIdentifier("videoCell")
                let thumbnailPath = "\(thisContent.imagePath).png"
                
                if let image = UIImage(named:thumbnailPath) {
                    tableView.beginUpdates()
                    let imageSize = image.size                      
                    let ratio = image.size.height / image.size.width
                    
                    // Make the frame the right size to show the thumbnail
                    let cellFrame = CGRectMake(0, 0, tableView.contentSize.width, tableView.contentSize.width * ratio)
                    videoThumbCell?.frame = cellFrame
                    let imageView = videoThumbCell?.imageView // image view constraints pin all edges to the cell edges
                    imageView?.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
                    imageView?.translatesAutoresizingMaskIntoConstraints = true
                    imageView?.contentMode = .ScaleAspectFit
                    imageView?.image = image

                    // heightForRowIs is an array to store the row heights
                    heightForRowIs[ indexPath.row ] =  cellFrame.height //   newHeight
                    tableView.endUpdates()
                }
                return videoThumbCell!

etc.

The code above contains TWO significant problems that caused a bizarre behaviour that I couldn’t understand. The first problem is here:

let videoThumbCell = tableView.dequeueReusableCellWithIdentifier(“videoCell”)

It looks innocent enough, but videoThumbCell is referencing a class that inherits from UITableViewCell and extends it with a UIImageView element, plus some additional attributes, but here during dequeue I am dealing simply with a UITableViewCell.

It should have been:

let videoThumbCell = tableView.dequeueReusableCellWithIdentifier(“videoCell”) as! VideoTableViewCell

To access the correct class.

Later I have:

let imageView = videoThumbCell?.imageView

Now, given the first mistake, I reference an “imageView” attribute inside what should have been a UITableViewCell and later I assign an image to it.

The image appeared, but the imageView didn’t seem to be obeying it’s layout constraints, so everything seemed to work, but not properly!

I corrected the cell dequeue error and renamed the imageView to something else and now everything works as it should.

My advice:

  1. Make sure that when you dequeue a custom cell with your own class, remember to cast it correctly so that you reference the correct object class.

  2. Avoid using imageView as an attribute that references a UIImageView.

Paul