Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load tableview from bottom, scroll up (reverse tableview) (iOS)

I would like to load my tableview backwards, meaning the the tableView loads from bottom and scroll up to see more content.

First, I tried reversing the dataSource array. The contents are reversed, but, it still loads from the top, and the user has to scroll down to see more content.

I then tried loading the tableView from the bottom in viewWillAppear:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    if (self.conversationTableView.contentSize.height > self.conversationTableView.frame.size.height) {
        let offset = CGPoint(x: CGFloat(0), y: CGFloat(self.conversationTableView.contentSize.height - self.conversationTableView.frame.size.height))
        self.conversationTableView.setContentOffset(offset, animated: true)
    }
}

This attempt, however does not work since I am asynchronously downloading images (I'm using NSTextAttachment, which fills my UITextView within each cell). Everytime my placeholder is replaced with the real downloaded image, it causes the tableView content offset to shift (the placeholder's image height is almost always smaller than the height of downloaded image). So setting the contentOffset this way does not work.

How does one load the tableView from the bottom and scroll up to see more content?

like image 762
Josh O'Connor Avatar asked Apr 18 '17 19:04

Josh O'Connor


People also ask

How do I scroll to the top of a tableView table?

To scroll to the top of our tableview we need to create a new IndexPath . This index path has two arguments, row and section . All we want to do is scroll to the top of the table view, therefore we pass 0 for the row argument and 0 for the section argument. UITableView has the scrollToRow method built in.


2 Answers

The best way was to flip the tableView and it's cells. This way, if a cell were to change size (due to things like asynchronous downloading), you will still load from the bottom of the tableview than at an offset.

//In ViewDidLoad
conversationTableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));

//In cellForRowAtIndexPath
cell.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi));

Also: If you have a headerView, simply set it to the tableView.tableFooterView:

var tableHeaderView = UIView(frame: headerFrame)
tableHeaderView.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi));
conversationTableView.tableFooterView = tableHeaderView

And if you have a footerView and headerView, just set the header to the footer, and the footer to the header.

Edit: If you want to flip the scroll indicator:

conversationTableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, conversationTableView.bounds.size.width - 8.0)
like image 128
Josh O'Connor Avatar answered Sep 24 '22 00:09

Josh O'Connor


In your viewWillAppear method, do the following:

tableView.scrollToRowAtIndexPath(bottomIndexPath, atScrollPosition: .Bottom,
      animated: true)

Where bottomIndexPath is the indexPath for the final row in your table view. If you have an array of length n and only one section in your table, this will usually be IndexPath(item: n-1, section: 0), but be sure to check your specific UITableView.

This will ensure you start off at the bottom of the tableView. Having done that, all you need to do is ensure your cellForRowAtIndexPath method on your UITableViewDataSource returns the data in reverse and you'll get the effect you want.

like image 45
Pedro Castilho Avatar answered Sep 25 '22 00:09

Pedro Castilho