I want to implement a TableView with a Custom TableViewCell showing an image.
To make this simple, I simply put a UIImageView inside a tableviewcell using autolayout (illustrated below).
What I want is to display the image inside a UIImageView however those images dimensions can be anything and are inconsistent (portrait, landscape, square) ...
Therefore, I'm looking to display an image with a fixed width (the width of the device) and a dynamic height that respect the ratio of the images. I want something like this:
I unfortunately didn't manage to reach that result.
Here's how I implemented it - (I'm using Haneke to load the image from an URL - image stored in Amazon S3):
class TestCellVC: UITableViewCell { @IBOutlet weak var selfieImageView: UIImageView! @IBOutlet weak var heightConstraint: NSLayoutConstraint! func loadItem(#selfie: Selfie) { let selfieImageURL:NSURL = NSURL(string: selfie.show_selfie_pic())! self.selfieImageView.hnk_setImageFromURL(selfieImageURL, placeholder: nil, format: HNKFormat<UIImage>(name: "original"), failure: {error -> Void in println(error) }, success: { (image) -> Void in // Screen Width var screen_width = UIScreen.mainScreen().bounds.width // Ratio Width / Height var ratio = image.size.height / image.size.width // Calculated Height for the picture let newHeight = screen_width * ratio // METHOD 1 self.heightConstraint.constant = newHeight // METHOD 2 //self.selfieImageView.bounds = CGRectMake(0,0,screen_width,newHeight) self.selfieImageView.image = image } ) } override func viewDidLoad() { super.viewDidLoad() // Register the xib for the Custom TableViewCell var nib = UINib(nibName: "TestCell", bundle: nil) self.tableView.registerNib(nib, forCellReuseIdentifier: "TestCell") // Set the height of a cell dynamically self.tableView.rowHeight = UITableViewAutomaticDimension self.tableView.estimatedRowHeight = 500.0 // Remove separator line from UITableView self.tableView.separatorStyle = UITableViewCellSeparatorStyle.None loadData() } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell = tableView.dequeueReusableCellWithIdentifier("TestCell") as TestCellVC cell.loadItem(selfie: self.selfies_array[indexPath.row]) // Remove the inset for cell separator cell.layoutMargins = UIEdgeInsetsZero cell.separatorInset = UIEdgeInsetsZero // Update Cell Constraints cell.setNeedsUpdateConstraints() cell.updateConstraintsIfNeeded() cell.sizeToFit() return cell } }
My calculation of the dynamic Height is correct (I've printed it). I've tried both method (describe in the code) but none of them worked:
See Results of Method 1 and 2 here:
Here is the essential problem: the only way in which UIImageView interacts with Auto Layout is via its intrinsicContentSize property. That property provides the intrinsic size of the image itself, and nothing more.
To maintain aspect ratio I calculated the width of UIImageView = (320/460)*450 = 313.043 dynamically. And set the contentMode For UIImageView is UIViewContentModeScaleAspectFit. And set the image(320x460) to image view but it is some what blur.
In the storyboard add trailing, leading, bottom and top constraints to your UIImageView
. After you load your image all you need to do is add an aspect constraint to your UIImageView
. Your images cell would look something like this:
class ImageTableViewCell: UITableViewCell { @IBOutlet weak var customImageView: UIImageView! internal var aspectConstraint : NSLayoutConstraint? { didSet { if oldValue != nil { customImageView.removeConstraint(oldValue!) } if aspectConstraint != nil { customImageView.addConstraint(aspectConstraint!) } } } override func prepareForReuse() { super.prepareForReuse() aspectConstraint = nil } func setCustomImage(image : UIImage) { let aspect = image.size.width / image.size.height let constraint = NSLayoutConstraint(item: customImageView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: customImageView, attribute: NSLayoutAttribute.height, multiplier: aspect, constant: 0.0) constraint.priority = 999 aspectConstraint = constraint customImageView.image = image } }
You can check working example here DynamicTableWithImages
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With