Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIImageView with Aspect Fill inside custom UITableViewCell using AutoLayout

I've been struggling with fitting an UIImageView which shows images of variable widths and heights with Aspect Fill. The cell height is not adapting to the new height of the UIImageView and persist it's height.

The hierarchy of the views is this

  • UITableViewCell
    • UITableViewCell.ContentView
      • UIImageView

I tried these scenarios in XCode Auto Layout :

  • set the UIImageView => Height to remove at build time
  • set the Intrinsic Value of the UIImageView to placeholder
  • set the Intrinsic Value for each of the UIImageView, ContentView and UITableViewCell to placeholder

With any of these combinations I get this view:

http://i.stack.imgur.com/Cw7hS.png

The blue lines represent the cell borders (boundaries) and the green ones represent the UIImageView border (boundaries). There are four cells in this example, the 1st and the 3rd ones have no images and the 2nd and the 4th ones have the same image (overflowing over the ones which have none).

like image 349
Mickey Mouse Avatar asked Mar 15 '15 16:03

Mickey Mouse


Video Answer


1 Answers

I cobbled together a solution based on two previous answers:

  • https://stackoverflow.com/a/26056737/3163338 (See point 1)
  • https://stackoverflow.com/a/25795758/3163338 (See point 2)

I wanted to keep the AspectRatio of the image regardless of its Height while fixing up the Width according to that of the UIImageView, the container of the image.

The solution comprises of :

  1. Adding a new AspectRatio constraint

    let image = UIImage(ContentFromFile: "path/to/image")
    let aspect = image.size.width / image.size.height
    
    aspectConstraint = NSLayoutConstraint(item: cardMedia, attribute:  NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: cardMedia, attribute: NSLayoutAttribute.Height, multiplier: aspect, constant: 0.0)
    

    when adding this constraint, xCode will complain about the new "redundant" constraint and attempt to break it, rendering it useless, yet displaying the image exactly like I want. This leads me to the second solution

    1. Lowering the priority of the new constrain to '999' seems to stop xcode from breaking it, and it stopped showing warning message about the new constraint

      aspectConstraint?.priority = 999

Not sure why xCode automatically adds UIView-Encapsulated-Layout-Height and UIView-Encapsulated-Layout-Height at build/run time; however, I learned how to respect that and live with it :)

Just leaving the solution here for anyone to check. This is working on iOS 8. I tried with iOS7 but it doesn't work the same as you need to implement tableView:heightForRowAtIndexPath calculating the height of the cell based on all the items contained within it and disable setting up:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44.0
like image 92
Mickey Mouse Avatar answered Sep 24 '22 16:09

Mickey Mouse