Table View with the cells having fixed height and dynamic height

674 Views Asked by At

I have a single tableview with multiple sections. In 1st section I want 4 tableview cells with fixed height whereas in all other sections I want tableview cells with dynamic height. The Problem is that when I am populating the table view the dynamic cell in the section > 0 cells are not resizing according to the content.

For dynamic height, I used following lines in my viewDidLoad view controller delegate.

tableView.estimatedRowHeight = 83
tableView.rowHeight = UITableViewAutomaticDimension

and the other methods are:

func numberOfSections(in tableView: UITableView) -> Int {
    return configRowsInSection.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    //configRowsInSection = listingsDetail.Specifications[IndexPath.sec].Configurations
    switch (section) {
       case 0:
          return 4
       default: 
        return Configurations.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.section == 0 {
        if indexPath.row == 0 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "BannerCell", for: indexPath) as! BannerCell
            cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
            cell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
            //addPageControl(cell.collectionView)
            
        }
        else if indexPath.row == 1 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "DetailCell", for: indexPath) as! DetailCell
            cell.Model.text = formatTitle(listingDetail: listingsDetail) 
            cell.SerialNumber.text = "Serial# " + listingsDetail.SerialNumber
        }
        else if indexPath.row == 2{
            let cell = tableView.dequeueReusableCell(withIdentifier: "PriceCell", for: indexPath) as! PriceCell
            cell.Price.text = "PRICE  "+listingsDetail.AskingPrice!
        }
        else if indexPath.row == 3 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "HighlightCell", for: indexPath) as! HighlightCell
            cell.filterText.text = listingsDetail.filter
            cell.seatsText.text = listingsDetail.seats
            cell.wheelsText.text = listingsDetail.wheels
            cell.hoursText.text = listingsDetail.hours
        }
    }
    else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "SpecificationCell", for: indexPath) as! SpecificationCell
        cell.configValueBig.text = specificationDetail[indexPath.section-1].Configurations[indexPath.row].Desc
    }
    return UITableViewCell()
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    var rowHeight:CGFloat!
    if indexPath.section == 0 {
        if indexPath.row == 0 {
            rowHeight = 200
        }
        else if indexPath.row == 1 {
            rowHeight = 100
        }
        else if indexPath.row == 2 {
            rowHeight = 70
        }
        else {
            rowHeight = 144
        }
        return rowHeight
    }
    else {
        rowHeight = 83
        //rowHeight = UITableView.automaticDimension (This makes the row height as -1) 
    }
    return rowHeight
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return 83
}

What is best way to handle a table view having one section with the rows of fixed height and other dynamic sections with the rows having variable height. Thanks in advance!

2

There are 2 best solutions below

1
Ahmed Abd Elaziz On

Try to make sure that your second section has the correct constraints from the bottom side. The best way to handle dynamic height is to use UITableView.automaticDimension

func numberOfSections(in tableView: UITableView) -> Int {
    return configRowsInSection.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    //configRowsInSection = listingsDetail.Specifications[IndexPath.sec].Configurations
    switch (section) {
       case 0:
          return 4
       default: 
        return Configurations.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.section == 0 {
        if indexPath.row == 0 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "BannerCell", for: indexPath) as! BannerCell
            cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
            cell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
            //addPageControl(cell.collectionView)
            
        }
        else if indexPath.row == 1 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "DetailCell", for: indexPath) as! DetailCell
            cell.Model.text = formatTitle(listingDetail: listingsDetail) 
            cell.SerialNumber.text = "Serial# " + listingsDetail.SerialNumber
        }
        else if indexPath.row == 2{
            let cell = tableView.dequeueReusableCell(withIdentifier: "PriceCell", for: indexPath) as! PriceCell
            cell.Price.text = "PRICE  "+listingsDetail.AskingPrice!
        }
        else if indexPath.row == 3 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "HighlightCell", for: indexPath) as! HighlightCell
            cell.filterText.text = listingsDetail.filter
            cell.seatsText.text = listingsDetail.seats
            cell.wheelsText.text = listingsDetail.wheels
            cell.hoursText.text = listingsDetail.hours
        }
    }
    else {
        let cell = tableView.dequeueReusableCell(withIdentifier: "SpecificationCell", for: indexPath) as! SpecificationCell
        cell.configValueBig.text = specificationDetail[indexPath.section-1].Configurations[indexPath.row].Desc
    }
    return UITableViewCell()
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    var rowHeight:CGFloat!
    if indexPath.section == 0 {
        if indexPath.row == 0 {
            rowHeight = 200
        }
        else if indexPath.row == 1 {
            rowHeight = 100
        }
        else if indexPath.row == 2 {
            rowHeight = 70
        }
        else {
            rowHeight = 144
        }
        return rowHeight
    }
   
    return UITableView.automaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}
0
sonal On

For all the custom cells in cellForRowAtIndexPath we need to return cell:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
    if indexPath.row == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "BannerCell", for: indexPath) as! BannerCell
        cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
        cell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
        //addPageControl(cell.collectionView)
        return cell
    }
    else if indexPath.row == 1 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "DetailCell", for: indexPath) as! DetailCell
        cell.Model.text = formatTitle(listingDetail: listingsDetail) 
        cell.SerialNumber.text = "Serial# " + listingsDetail.SerialNumber
        return cell
    }
    else if indexPath.row == 2{
        let cell = tableView.dequeueReusableCell(withIdentifier: "PriceCell", for: indexPath) as! PriceCell
        cell.Price.text = "PRICE  "+listingsDetail.AskingPrice!
        return cell
    }
    else if indexPath.row == 3 {
        let cell = tableView.dequeueReusableCell(withIdentifier: "HighlightCell", for: indexPath) as! HighlightCell
        cell.filterText.text = listingsDetail.filter
        cell.seatsText.text = listingsDetail.seats
        cell.wheelsText.text = listingsDetail.wheels
        cell.hoursText.text = listingsDetail.hours
        return cell
    }
}
else {
    let cell = tableView.dequeueReusableCell(withIdentifier: "SpecificationCell", for: indexPath) as! SpecificationCell
    cell.configValueBig.text = specificationDetail[indexPath.section-1].Configurations[indexPath.row].Desc
  return cell
}
return UITableViewCell()

}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 83

}