Static tableview How do I make the last visible row to occupy remaining space in

462 Views Asked by At

There are 5 static cells. When I show all 5 cells, it's fine but If I hide some cell by returning height as zero and the last visible cell is not same as last cell of tableview in storyboard then confusion comes as to how to do that ?

   override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return hideRow(at: indexPath) ? 0: UITableView.automaticDimension
    }

enter image description here

IMO , If last visible row in tableview and lastrow in tableview is same

 return indexPath.row == 4 ? 150 : tblHeight - 150

 override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
             if hideRow(at: indexPath) {
               return 0 
             }
             else {
               let tblHeight = infoTable.bounds.size.height
                if indexPath.row == 4 {
                  return tblHeight - yPlusHeightOfPreviousCell
                }
               return UITableView.automaticDimension
             }
       }

But the problem now what if 3rd is last row and for 4th and 5th I'm returning 0 as height to hide it.

Then how to make the last visible cell expand and occupy the full space

1

There are 1 best solutions below

10
DonMag On

Add an empty UIView as the table footer view:

class StaticTableViewController: UITableViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.tableFooterView = UIView()
    }
    
}

Edit After re-reading your question...

The above code will "hide" the empty rows.

If your goal is to make the "last visible row" fill the remaining height, that will be more considerably complex.

Since your current approach is using a static table view and you won't be doing any scrolling, a much easier approach would be to use a UIStackView with custom views instead of cells. Then everything would be handled by auto-layout, constraints, and the stack view, and you wouldn't need to do any calculating.


Edit 2a - move code to a function

Add these vars to your table view controller class:

var numRows: Int = 5
var lastVisibleRow: Int = -1
var lastRowHeight: CGFloat = -1
var curTableWidth: CGFloat = 0

Add this function:

func updateTable() -> Void {
    lastVisibleRow = -1
    var h: CGFloat = 0
    // find last visible row
    //  and sum of row heights
    for i in 0..<numRows {
        let r = tableView.rectForRow(at: IndexPath(row: i, section: 0))
        h += r.height
        if r.height > 1.0 {
            lastVisibleRow = i
        }
    }
    // get rect of last visible row
    let r = tableView.rectForRow(at: IndexPath(row: lastVisibleRow, section: 0))
    // subtract its height from the sum of heights
    h -= r.height
    // set calculated last row height
    lastRowHeight = tableView.frame.height - h + tableView.bounds.origin.y
    // reload the last visible row
    //tableView.reloadRows(at: [IndexPath(row: lastVisibleRow, section: 0)], with: .none)
    tableView.reloadData()
}

Call it from viewDidLayoutSubviews() anytime the table width changes:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    // we only run the following block
    //  if the tableView width has changed
    if curTableWidth != tableView.frame.width {
        curTableWidth = tableView.frame.width
        updateTable()
    }
}

and change your heightForRowAt to this:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if hideRow(at: indexPath) {
        // row should be hidden
        return 0
    } else if indexPath.row == lastVisibleRow {
        // if it's the last visible row,
        return lastRowHeight
    }
    // else
    return UITableView.automaticDimension
}

Then, anytime you change the rows (based on user-interaction or whatever), call reloadData on the tableView, and then call updateTable() to re-calculate the last visible row and its height.