Dynamically set UIScrollView and UITableView heigh

2019-09-19 03:35发布

问题:

Im quite new to iOS development and i've been stuck with this for a couple of days

i have a UITableView and UIImageView inside a UIScrollView, the UIImageView is on top of the table and the height is static so i don't have any issues with that, the problem is the UITableView, i need to get the height dynamically based on the content and set that height to a height constraint of the table and the contentsize of the scrollview.

The cells are self sizing, so the height of the cell varies depending on the content. The best i could do so far is getting the height by using contentSize.height property of UITableView but apparently this returns a height based on the estimatedRowHeight i set, not te actual height of each row.

the code:

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self
    tableView.estimatedRowHeight = rowHeight
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.layoutIfNeeded()
    tableHeight.constant = tableView.contentSize.height
    scrollView.contentSize.height = imageView.bounds.height + tableView.contentSize.height
}

What i've tried:

  • Getting the height by using contentSize.height property of UITableView, as shown in the code and explained before.
  • Getting the height of each row individually on willDisplayCell and add it to the height constraint of the table and the contentSize of the scrollview. But looks like this adds more rows than actually are, giving me a bunch of empty cells at the end of the table. the code inside willDisplayCell:

    let cellHeight = cell.bounds.height
    tableHeight.constant += cellHeight
    scrollView.contentSize.height += cellHeight
    
  • The same as before, except i tried inside cellForRowAtIndexPath with the same result.

回答1:

The Apple documentation discourages embedding UITableView within a UIScrollView:

You should not embed UIWebView or UITableView objects in UIScrollView objects. If you do so, unexpected behavior can result because touch events for the two objects can be mixed up and wrongly handled.

To solve your problem, you could put the UIImageView in a header view, or change the cell of your first row to display an image. You would then adjust the cell heights using your UITableViewDelegate, specifically tableView:heightForRowAtIndexPath:.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // adjust the return based on the indexPath
    return 30;
}


回答2:

i had the same problem and i found a solution. I have a TableView inside of UIScrollView and didn't know how to set dynamically height of UIScrollView. First of all u have to set up your scrollView, u can check it here in stackOverFlow (How to use UIScrollView in Storyboard). The next step is to set tableView's constraints to scrollView(it should be tableView's superView): leading,trailing and bottom (bottom is 0 and others whichever u want), and the top constraint to the closest object with constant whichever you want. So now you have to set dynamically height of UIScrollView. It depends on 2 things: your device screen's height and tableView's height (because tableView's content is dynamically). You have to use this extension to make device determination more comfortable: iOS: How to determine the current iPhone/device model in Swift? After those things i did this:

var viewHeight: CGFloat = 0

var modelDevice: String {
   get {
  return UIDevice.currentDevice().modelName
  }
}

var tableViewHeight: CGFloat {
   get {
   // 90 is my tableViewCell's row height
  return CGFloat(detail.cart.count) * 90 
  }
 }

 func configureSelfHeight(modelDevice: String) {
   switch modelDevice {
   case "iPhone 4", "iPhone 4s": viewHeight = 480
   case "iPhone 5", "iPhone 5c", "iPhone 5s", "iPhone SE": viewHeight = 568
   case "iPhone 6", "iPhone 6s", "iPhone 7": viewHeight = 667
   case "iPhone 6 Plus", "iPhone 6s Plus", "iPhone 7 Plus": viewHeight = 736
   default: viewHeight = 568
   }
  scrollView.contentSize.height =  viewHeight + tableViewHeight
 }

and just call this method inside of viewDidLayoutSubviews():

 override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    configureSelfHeight(modelDevice)
}

I hope it will help you.:)