Remembering scroll position on UITableView
Asked Answered
V

8

34

I have a bit of a problem with my iOS app in xcode. I have a UITableView that loads a few hundred cells. When I scroll down to a specific cell and drill down to detailedviewcontrollers and return again the master view table has returned all the way to the top. I've had a look at the following 2 questions that are similar.

How can I get the UITableView scroll position so I can save it?

Setting scroll position in UITableView

I still can't get these to work. I'm not the most experienced coder so I'm really struggling with this.

I know things like viewWillDisappear and viewDidAppear need to be changed, but I just really can't get much further than that.

On this table I have a reloadData feature so it is possible to pull down the latest data from the server and also a working search bar.

Anyway, a helping hand would be great. Thanks,

Luke

Virago answered 17/9, 2013 at 7:15 Comment(2)
That's not the default behavior. Seems like somewhere in your code you are scrolling to the top. If you delete that line, you should be all set. Search for scrollToRowAtIndexPath maybe.Sapling
your table is scrolling back to the top when it comes back into view most likely because you're doing a "reloadData" call on it in that view controller's "viewWillAppear:" method.Homans
V
13

Sorted!

With a bit of inspiration from Desdenova, whilst at work I had a good think about it and realised what it could be. Remembering that I had a search bar, I had implemented the following code a few months ago to hide it:

[self.tableView setContentOffset:CGPointMake(0,-20) animated:NO];

In naivety I put that in viewDidAppear rather than viewDidLoad. Obviously, this did hide the search bar, but with it being in the wrong void command it did it every time the masterDetailView returned to the top of the stack. So, after moving the above code to viewDidLoad it now still hides it, but only the once.

I'm just spelling it out like this for other beginners, like myself, who may come across the same problem and may just save their sanity!

Thanks to you all for your ideas that helped me out.

+1 to you all!

Virago answered 17/9, 2013 at 16:56 Comment(1)
Perfect. Thanks.Sprout
J
70

See here you have to first save the scrolled position of tableView i.e. contentOffset of tableView and then reuse it when you are coming back to tableView.

1)When and where you will save it :

When : At the point, when you are drilling down to detailViewController save the contentOffset of tableView

How : float verticalContentOffset = tableView.contentOffset.y;

2) How will you set tableView back to the same scrolled position :

[tableView setContentOffset:CGPointMake(0, verticalContentOffset)];

Hope this will help you.

Jook answered 17/9, 2013 at 8:21 Comment(1)
Any idea on how to achieve this for a messaging app? As in scrolling up loads more rows but current Y offset is always 0. Meaning that setting the contentOffset to Y = 0 will just scroll that table to the top againHett
V
13

Sorted!

With a bit of inspiration from Desdenova, whilst at work I had a good think about it and realised what it could be. Remembering that I had a search bar, I had implemented the following code a few months ago to hide it:

[self.tableView setContentOffset:CGPointMake(0,-20) animated:NO];

In naivety I put that in viewDidAppear rather than viewDidLoad. Obviously, this did hide the search bar, but with it being in the wrong void command it did it every time the masterDetailView returned to the top of the stack. So, after moving the above code to viewDidLoad it now still hides it, but only the once.

I'm just spelling it out like this for other beginners, like myself, who may come across the same problem and may just save their sanity!

Thanks to you all for your ideas that helped me out.

+1 to you all!

Virago answered 17/9, 2013 at 16:56 Comment(1)
Perfect. Thanks.Sprout
S
1

If anyone is wondering, I tried the solution by Prashant N and it worked. However reloadData don't actually reset the scroll position anymore now, so I didn't have to do anything other than reloadData.

Slugabed answered 11/4, 2016 at 7:5 Comment(0)
A
1

My solution to this problem consisted in scrolling the table to the indexrow of the last item.

private func scrollToItem(item:Int, section:Int bottom:Bool = true, animated:Bool = false) {
    let indexPath = NSIndexPath(forRow: item:Int-1, inSection: section)
    var position = UITableViewScrollPosition.Bottom
    if (!bottom) { position = UITableViewScrollPosition.Top }
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: position, animated: animated)
}
Abeyant answered 9/9, 2016 at 10:37 Comment(0)
B
1

For some reason this was halfway working for me (sometimes the position would only be approximate). I finally used the following a priori less clean solution

NSIndexPath *firstVisibleIndexPath = [[self.tableView indexPathsForVisibleRows] objectAtIndex:0];
[self.tableView scrollToRowAtIndexPath:self.firstVisibleIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
self.firstVisibleIndexPath = firstVisibleIndexPath;

which worked better.

Beckybecloud answered 25/1, 2017 at 7:2 Comment(3)
A fairly long winded route approach, but should work well. Why are you storing the index path as an instance variable? I assume this is just something specific to your project?Virago
Well I thought I was answering something slightly different, this is for a use case with a segmented control and 2 segments. So when you switch segment you save the indexPath for the next time you will come to this segment (observe that the property is set after the scroll is done)Beckybecloud
Does this update the firstVisibleIndexPath when you stay on the screen and keep playing with tableview by scrolling it up and down? In which event or delegate method do you update firstVisibleIndexPath continuously when the table is scrolled?Raposa
J
0

As mentioned in other comments, scrolling to the top on Back navigation in a UINavigationController is not the default behavior.

Another cause might be that you are setting a cell near the top of the table as first responder in viewWillAppear, e.g. a search box or edit field near the top of your table. UITableViewController will scroll a first responder into view automatically, which is nice. As long as that's what you're trying to do. :) Take care to not set first responder in viewWillAppear unless that's what you want. Cheers, AZ

Jesu answered 4/5, 2017 at 21:44 Comment(0)
A
0

My decision for a collection:

CGFloat oldCollectionViewHeight = self.messageCollectionView.contentSize.height;

[self.messageCollectionView reloadData];
[self.messageCollectionView layoutIfNeeded];

CGFloat newCollectionViewHeight = self.messageCollectionView.contentSize.height;

if (oldCollectionViewHeight) {
    self.messageCollectionView.contentOffset = CGPointMake(0, newCollectionViewHeight - oldCollectionViewHeight);
}

For the table, the principle is the same.

Ambulacrum answered 27/12, 2017 at 15:14 Comment(0)
P
0

You don’t need to do anything, while you are in the same view controller, your position will be the same. I’m afraid that somewhere in your view controller is being called a reloadData. Search for some method calling scrollToRowAtIndexPath.

Potentate answered 10/10, 2018 at 15:5 Comment(1)
Yeah, I got it sorted. The solution was in the accepted answer.Virago

© 2022 - 2024 — McMap. All rights reserved.