1

I have tableview cell like this.

enter image description here

And I update that image height constraint and reload. I am using auto-resizing cell and testing on iOS 10.

How to animate UITableViewCell height using auto-layout?

imageHeightConstraint.constant = 200 //example only. it will be dynamic. Some image height will be 200, 400, etc
self.contentView.layoutIfNeeded()
UIView.setAnimationsEnabled(false)
self.delegate?.getTableView!().beginUpdates()
self.delegate?.getTableView!().endUpdates()
UIView.setAnimationsEnabled(true)

I tried to reload only 1 row too and not okay.

self.contentView.layoutIfNeeded()
let indexPath = IndexPath(item: self.tag, section: 0)
self.delegate?.getTableView!().beginUpdates()
self.delegate?.getTableView!().reloadRows(at: [indexPath], with: .none)
self.delegate?.getTableView!().endUpdates()

Problem is it doesn't change height at all unless I reload table like this.

imageHeightConstraint.constant = 200
self.delegate?.getTableView!().reloadData()

But I don't want to call reloadData since it will reload all visible cell and resource intensive (laggy too when user scroll quickly). How shall I update my image constraint properly and update table view cell (auto-resizing) height correctly?

Edit - Using with intrinsic size

I delete my height constraint and just use property of intrinsic size in UIImageview. Then height is correct but width is too big (since it is intrinsic). How shall I do?

enter image description here

Khant Thu Linn
  • 5,905
  • 7
  • 52
  • 120
  • **I tried to reload only 1 row too and not okay.** -> It is right code . in cellForRow how you are changing height of image for same cell? , And how you identify cell that you need to change height ? – Prashant Tukadiya Sep 08 '17 at 07:29
  • I change image height constraint and everytime after I change that constraint, I reload cell . Each cell has tag which is equal to indexPath.row. – Khant Thu Linn Sep 08 '17 at 07:32
  • In past , I had this scenario where i need to expand cell, What I did is that i keep track of indexPath Globally , and did same What you did for reload 1 Row as well as keep `indexPath` save to global object , and in cell for row i check if current indexPath matches with global indexPath then set whatever constant is – Prashant Tukadiya Sep 08 '17 at 07:37

1 Answers1

0

ImageViews have intrinsic size. That means they take size based on the content of image. Unless you apply the width and height constraint on image ur imageView should be able to resize itself as per the image size.

You can make use of tableView's height property

    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.estimatedRowHeight = 100

Now select your cell and set the leading, trailing,top and bottom constraint. Make sure not to set height/aspect ratio constraint manually.

enter image description here

Now if you simply load the image to imageView, cell will automatically take size based on the size of the image.

Edit:

This works if the image you are loading is in specific size range. If you want to scale down the image or set the height constraint to image and update its height once you download the image, you need not reload the whole tableView rather you can reload a specific cell in tableView

self.tableView.reloadRows(at: [yourIndexPath], with: .none)

In this case make sure you implement

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
}

EDIT:

Set your imageView content mode to AspectFit or AspectFill from ScaleTofill

Sandeep Bhandari
  • 19,999
  • 5
  • 45
  • 78
  • I need to download image from my backend server and after that, I set imageview. So, can I rely on intrinsic size? I feel like it need to reload cell again since cell layout is already done after image is downloaded. – Khant Thu Linn Sep 08 '17 at 07:46
  • @khant-thu-linn : You can reload a specific cell rather than reloading the whole tableView – Sandeep Bhandari Sep 08 '17 at 07:47
  • @khant-thu-linn : Better thing to do would be server sends you the aspect ratio of the image you need to load, and height for row at index path u calculate the height for the specified aspect ratio as width of imageView is fixed and return the same. What happens here is when u actually download the data your cell need not layout itself again as the cell will already be big enough to hold image. Thats why in apps when they load image async layout won't change – Sandeep Bhandari Sep 08 '17 at 07:50
  • Ah got it. I have updated my question. I have followed your suggestion and height is correct but width is wrong. How shall I do? – Khant Thu Linn Sep 08 '17 at 07:51
  • Yes. I always want server to send me aspect ratio but the backend developer want to fight with me every time i suggest that. :D . – Khant Thu Linn Sep 08 '17 at 07:52
  • @khant-thu-linn : Same story everywhere :D – Sandeep Bhandari Sep 08 '17 at 07:52
  • In heightforrow, I return UITableViewAutomaticDimension and I change my imageview to ScaleTofill. My one become something like this. It is still not okay. http://i68.tinypic.com/spviip.png – Khant Thu Linn Sep 08 '17 at 08:04
  • @khant-thu-linn : What is the content mode of ur imageView? Make it aspect fit – Sandeep Bhandari Sep 08 '17 at 08:05
  • I have change to aspect fit and it show like this. It look like both aspectfit, aspectfill, scale to fill are not okay. http://i66.tinypic.com/i5qa2s.png – Khant Thu Linn Sep 08 '17 at 08:08
  • @khant-thu-linn : Can u show me the original image ? You sure you haven't set height for cell anywhere ? Finally u sure the imageView content mode is AspectFit ? If yes to all, then show me original image as I cant figure out whats the issue buddy – Sandeep Bhandari Sep 08 '17 at 08:10
  • @khant-thu-linn : what you showed in http://i66.tinypic.com/i5qa2s.png looks fine to me. The original image u shared looks like a landscape image so when u render it in tableView portrait mode width is not enough so it tried respecting the aspect ratio of image and fit the image that matches ur width. – Sandeep Bhandari Sep 08 '17 at 08:19
  • But it has extra height in i66.tinypic.com/i5qa2s.png. (white background). I don't know how come it is longer. – Khant Thu Linn Sep 08 '17 at 08:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/153930/discussion-between-sandeep-bhandari-and-khant-thu-linn). – Sandeep Bhandari Sep 08 '17 at 08:24
  • I don't think this actually works, or I missed something. – Jonny Jan 25 '18 at 04:54
  • Btw I don't think it's possible to call `reloadRows at indexpath`, granted that we use `cellForRowAtIndexPath` for actually fetching an arbitrarily sized and aspectratio:ed image from network. This would create an infinite loop, so what we need to do is to refresh the layout only; at best make use of the intrinsic size of the fetched image. I have so far failed in my attempts. – Jonny Jan 25 '18 at 05:08