-1

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

CuriousMan
  • 42
  • 11
  • I think you are looking for this ```infoTable.tableFooterView = UIView()``` write this inside viewDidLoad to remove bottom extra rows. Or by using your approach ```indexPath.row == arrayData.count - 1``` compare last index. – Raja Kishan Sep 15 '21 at 02:49
  • Hi , I want the last visible to occupy the rest of the space. so that It appears at bottom of the screen – CuriousMan Sep 15 '21 at 03:08
  • I'd like to show the last visible row to occupy the remaining space. Let's say third index is last visible and 4th and 5th height zero hence , it won't be visible. Now how I make sure third row occupies the remaning height of tableview – CuriousMan Sep 15 '21 at 03:25

1 Answers1

0

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.

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • Yes you are right , but here I will have to stick with Tableview as a result of legacy code. My goal is to make the "last visible row" fill the remaining height. Any suggestions are appreciated – CuriousMan Sep 16 '21 at 00:07
  • 1
    @RaviMan - well, there is potentially a lot of "moving parts" to deal with. When are you determining which rows to show? At `viewDidLoad()`? Or, are you showing/hiding rows dynamically based on user interactions? Are your static cells fixed heights, or may the heights vary based on view width? I'd suggest editing your question and including "real world" cell contents (I'm assuming the image you posted isn't really what you're planning on displaying), and more detail about how and when you're determining which rows you want to show and hide. – DonMag Sep 16 '21 at 00:40
  • HeightForRowAtIndex... that's where I'm deciding what to show(Automaticdimension as height) and what to hide(0 as the height) based on the business logic for particular indexpath. – CuriousMan Sep 16 '21 at 01:37
  • 1
    @RaviMan - well, no... you're setting the row height in `heightForRowAt` ... presumably, you have some data somewhere that is set ***before*** that call, and `hideRow(at: indexPath)` is returning true or false based on that data. So - where / when are you setting that data? – DonMag Sep 16 '21 at 02:25
  • I will be setting the value of the data to static cells in viewDidLoad. I will choose whether to show or hide in HeightForRowAtIndex by returning automaticdimension or 0 – CuriousMan Sep 16 '21 at 03:31
  • @RaviMan -- your answer doesn't make any sense, but since you won't (for some reason) provide more detail, the code under **Edit 2** in my answer may or may not work for you. – DonMag Sep 16 '21 at 16:23
  • I'm setting the data at viewdidLoad , I might choose to show or hide rows based on user interaction as well and data that's download from server api in viewdidload – CuriousMan Sep 17 '21 at 09:17
  • Cell height might change based on screen display width – CuriousMan Sep 17 '21 at 09:18
  • Basically there could be 15 rows and I will choose to some 5 rows out of that based on logic I downloaded in ViewDidload and further could change based on user internaction with 5 rows. But I want the fifth row to fill the remaining height. 5 rows are not fixed , It could be 2 , 5 ,4 – CuriousMan Sep 17 '21 at 09:20
  • 1
    @RaviMan - you may be able to make use of that code for your needs. See the **Edit 2a** for code arrangement and notes. – DonMag Sep 17 '21 at 12:57