iOS custom view inside table view cell with intrinsic height

Viewed 167

When UILabel with multi-line and wrap-word enabled is used on UITableViewCell, UITableView handles the different cell heights without any problem. UILabel calculates its height according to its content and its width.

I implemented a custom view (https://github.com/fthdgn/ios-demo/blob/master/demo/CustomGridView.swift) which also calculates its height according to its content and its width. This view is a simple grid view which determines row count and height according to column count which is determined by available width. However, there are problems when custom view is used on UITableViewCell.

On my demo application (https://github.com/fthdgn/ios-demo),

  • On the 1st tab [1st image], the custom view is used alone. Its height is correct. Button adds new items and updates it height correctly.
  • On the 2nd tab [2nd image], the height of the custom view is calculated wrongly. This height is calculated according to placeholder width of the view on the XIB file. This width is smaller than correct width, thus the height is longer than correct value.
  • Reload button on the 2nd tab [3rd image], reloads table. Custom view calculates and updates itself correctly.
  • On the 3rd tab [4th image], UILabel calculates its height according to available width from the start.

Why does not my custom view work like UILabel? Are there missing setNeedsLayout, invalidateIntrinsicContentSize calls?

TAB1 TAB2 TAB2_RELOAD TAB3

I updated the code to show only 1 row with 11 cells on UITableView. The width of Grid View on on XIB file is 300, because the selected device is 4S. The simulator I use is 11 Pro Max, it is wider than 4S. intrinsicContentSize and layoutSubviews call prints these:

  • content (-1.0, 50.0) frame (300.0, 0.5)
    First calls intrinsicContentSize. Frame is what is on the XIB, constraints does not resized the view yet. This width requires 50 height to place cells.
  • layout (394.0, 50.333333333333336)
    Calls layout, the height is determined according to intrinsicContentSize, width determined by UITableViewCell constraints. It is wider then the value which intrinsicContentSize is calculated by.
  • content (-1.0, 20.0) frame (394.0, 50.333333333333336)
    Because layout changed, I invalidate the intrinsicContentSize. New intrinsicContentSize value is calculated according to correct width. New height is 20.
  • layout (394.0, 50.333333333333336)
    Something triggers layout. Eventhough last intrinsicContentSize.height is 20, it still uses 50.
  • content (-1.0, 20.0) frame (394.0, 50.333333333333336)
    Layout invalidates intrinsicContentSize. intrinsicContentSize is recalculated but its value does not change.

After these calls, event though the last intrinsicContentSize wants 20 height, frame continues to be 50. You can see at 2nd screenshot, the row with 11 cell is longer than what it should be.

0 Answers
Related