Dynamic Height UITableView

I would like to set the UITableView according to the height for all the content in the table view.

This is my storyboard.

enter image description here

The problem with this is the top and bottom image. ImageView is always static on the screen.

enter image description here

It is assumed that there should be 10 elements in the table view, but due to screen size limitations only 7 appears. I would like to show all 10 before the user can see the bottom ImageView. (btw, all 3 types, i.e. both image representations and tableview are in uiscrollview)

IDEAL

enter image description here

Some of the other limitations that I have to work with are that the number of elements in the table view is dynamic, which can be in any quantity, usually less than 10, which I will later choose from the api. And cell height is also dynamic depending on the content.

I just started with simple code

class ExampleViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! var items: [String] = [ "Item 01", "Item 02", "Item 03", "Item 04", "Item 05", "Item 06", "Item 07", "Item 08", "Item 09", "Item 10"] override func viewDidLoad() { super.viewDidLoad() self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell") } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.items.count; } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell cell.textLabel?.text = self.items[indexPath.row] return cell } } 
+9
source share
7 answers

You need to set the IBOutlet to NSLayoutConstraint , which sets the height of the tableView (first you need to create a height constraint with any value, it doesn't matter) and then ctrl drag it to the class file

enter image description here

Then in your viewWillAppear you need to calculate the height of the tableView and set it. Like this:

 var tableViewHeight:CGFloat = 0; for (var i = tableView(self.tableView , numberOfRowsInSection: 0) - 1; i>0; i-=1 ){ tableViewHeight = height + tableView(self.tableView, heightForRowAtIndexPath: NSIndexPath(forRow: i, inSection: 0) ) } tableViewHeightLayout.constant = tableViewHeight 

And that is pretty much the case. This will give you the size of the scrollView content and should not cause any warnings.

+4
source
  • A subclass of your UITableView overrides intrinsicContentSize as its contentSize, for example:

     override var intrinsicContentSize: CGSize { return contentSize } 
  • Then use the automatic row height for your table, so your viewViewController viewDidLoad will have:

     tableView.estimatedRowHeight = 44 

    And the UITableViewDelegate function:

     func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return UITableViewAutomaticDimension } 
  • When you get data from your API and reload your table, just call:

     tableView.invalidateIntrinsicContentSize() 

    This will say that your table will resize to the same size as its contents (due to overriding), and place the bottom image as needed.


If your storyboard gives an error message indicating that your UIScrollView has an ambiguous height, because there are no height restrictions in the UITableView, select your UITableView and assign it an internal size placeholder in the size inspector.

+12
source

In this case, do not make your lower cell static, make it part of the table view and insert this lower image into the last row using the table delegate method - insertRowAtIndexPath

+1
source

In this case, add the View footer (red) as the footer of the table.

To add a footer to a UITableView , you can use:

 tableViewObj.tableFooterView = footerViewObj; 
+1
source

You probably need to implement the internal size of the contents of the table. Please check this one to see if it helps.

I remember this problem and even created a custom subclass of UITableView .

 #import "IntrinsicTableView.h" @implementation IntrinsicTableView #pragma mark - UIView - (CGSize)intrinsicContentSize { return CGSizeMake(UIViewNoIntrinsicMetric, self.contentSize.height); } #pragma mark - UITableView - (void)endUpdates { [super endUpdates]; [self invalidateIntrinsicContentSize]; } - (void)reloadData { [super reloadData]; [self invalidateIntrinsicContentSize]; } - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation { [super reloadRowsAtIndexPaths:indexPaths withRowAnimation:animation]; [self invalidateIntrinsicContentSize]; } - (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation { [super reloadSections:sections withRowAnimation:animation]; [self invalidateIntrinsicContentSize]; } - (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation { [super insertRowsAtIndexPaths:indexPaths withRowAnimation:animation]; [self invalidateIntrinsicContentSize]; } - (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation { [super insertSections:sections withRowAnimation:animation]; [self invalidateIntrinsicContentSize]; } - (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation { [super deleteRowsAtIndexPaths:indexPaths withRowAnimation:animation]; [self invalidateIntrinsicContentSize]; } - (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation { [super deleteSections:sections withRowAnimation:animation]; [self invalidateIntrinsicContentSize]; } @end 
+1
source

Try also

 in ViewDidLoad self.table.estimatedRowHeight = 44.0 ; self.table.rowHeight = UITableViewAutomaticDimension; 

Height for a line along a pointer path

 -(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return UITableViewAutomaticDimension;} 
+1
source

Update Swift 4, this code works well

 self.scrollView.layoutIfNeeded() self.view.layoutIfNeeded() self.tableViewHeightConstraint.constant = CGFloat(self.tableView.contentSize.height) 
0
source

Source: https://habr.com/ru/post/1239009/


All Articles