I am using iPhone SDK 3.1.3. I have a UITableViewController which gets data from another controller. The table view is added as a subview to the mainview but the frame is set so that it is not visible. The table view frame is updated and made to slide over the main view by tapping on a button.
The table view appears and I scroll to the last row. If I select the last row, I reload the table with more data. The table gets updated with more data. Everything works fine except the scroll position is always the top.
I need the scroll position to be the last row that I clicked on to load more data. I save the scroll position and call the following code after it loads more data. It executes without issues but the scroll position is always the top.
[theTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:savedScrollPosition inSection:0] atScrollPosition:savedScrollPosition animated:NO];
The above seems to have no effect. ViewWillAppear: ViewDidAppear: does not fire and I am told that if the view controller is instantiated in code, which is the case, these don't fire. Please help me figure out how and when to set the scroll position after the table is reloaded ([theTableView reloadData]) so that it is at the row that I clicked on.
Code to Reload table view & scroll
////performAction will notify the tableviewcontroller which will result in didPerformAction being called
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == lastRow)
{
savedScrollPosition = lastRow;
//perform the action
[controller performAction];
}
}
- (void) didPerformAction:(NSNotification *)obj
{
[theTableView reloadData];
[theTableView
scrollToRowAtIndexPath: [NSIndexPath indexPathForRow:savedScrollPosition inSection:0]
atScrollPosition:UITableViewScrollPositionBottom
animated:NO];
}
This seemed to do the trick.
[theTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:savedScrollPosition inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
CGPoint point = theTableView.contentOffset;
point .y -= theTableView.rowHeight;
theTableView.contentOffset = point;
It will look better and the scroll position will stay fixed if you can insert the rows instead of calling reloadData.
[theTableView beginUpdates];
[theTableView insertRowsAtIndexPaths:indexPaths withRowAnimation:animation];
// make sure the dataSource will return new rows before calling endUpdates
[theTableView endUpdates];
Instead of using UITableView scrolling you can use UIScrollView scrolling:
savedOffset = [theTableView contentOffset];
Then restore:
[theTableView setContentOffset:savedOffset];
If that's the actual code and assuming theTableView is not nil there, you should be getting a warning saying "may not respond to..." because scrollToRowAtIndexPath is spelled wrong.
Secondly, the atScrollPosition parameter expects a UITableViewScrollPosition enum value indicating where on the screen you want the target row to be positioned.
Try this:
[theTableView scrollToRowAtIndexPath:
[NSIndexPath indexPathForRow:savedScrollPosition inSection:0]
atScrollPosition:UITableViewScrollPositionBottom
animated:NO];
Related
I'm bulding a celander application and i want the calender to get scrolled to the current month when started. i used custom cell for each month. the code that i found to make this happen from this website is this:
[self.bahraincld reloadData];
NSIndexPath *scrollto = [NSIndexPath indexPathForRow:2 inSection:1];
[self.bahraincld scrollToRowAtIndexPath:scrollto
atScrollPosition:UITableViewScrollPositionTop animated:YES];
I'm using it in the view did load. it's giving me a signal SIGABRT.
is this code correct? where should i use it if i want it to work whenever the user starts the calendar.
Thanks.
You better put this code into viewDidAppear, because your tableView haven't loaded the data yet, so the cells are not created. In your case SIGABRT, is because row number 2 is beyond bounds.
Here is what i did, hop it helps someone.
//in the view will appear reload your table.
-(void)viewWillAppear:(BOOL)animated
{
[self.yourtable reloadData];
}
//in the view did appear, value = defining which costume cell to move to.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
int value = 5;
NSIndexPath *scrollto = [NSIndexPath indexPathForRow:value inSection:0];
[self.yourtable scrollToRowAtIndexPath:scrollto
atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
I've 3 tableviews in my view and I want to enable scroll to top feature for all tables at the same time, i.e., if the user taps on status bar all the three tables should be scrolled to top position.
I've tried using scrollsToTop property of all my tableViews and also various combinations of YES/No for this property. for example
table1.scrollsToTop = YES;
table2.scrollsToTop = NO;
table3.scrollsToTop = NO;
but not able to achieve this. Do we have any way out to get the event of tap on status bar so that I may try to set the content offset of all the tables to top position or any other work around.
Any help would be appreciated.
Solved this problem by overriding scrollViewShouldScrollToTop method like below, -
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView {
[table1 scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
[table2 scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
[table3 scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
return NO;
}
I am developing an Iphone application ,this contain a UITableview with 8 cells.I am implement an NSMutableArray for store each cells when the cell creation time ,but the tableview load time only provide the displayed cell store to the array.For avoid this issue i have autoscroll the table view and get the total cell for store to the array with the following code;
-(void)viewDidAppear:(BOOL)animated{
[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[musicGenre count]-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
This is working perfectly.But now i want scroll this from bottom to top at the same time(load time) .How to implement this ?
Thanks in Advance.
Since UITableView inherits from UIScrollView you could use something like this:
- (void)viewDidAppear:(BOOL)animated{
[table setContentOffset:CGPointMake(0.0, table.contentSize.height - table.bounds.size.height)
animated:NO];
[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[musicGenre count]-1 inSection:0]
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
}
EDIT:
If you want the initial move from top to bottm also animated simply use:
- (void)viewDidAppear:(BOOL)animated{
[table setContentOffset:CGPointMake(0.0, table.contentSize.height - table.bounds.size.height)
animated:YES];
[tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[musicGenre count]-1 inSection:0]
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
}
But please consider user experience - is that ammount of animation needed? Because users (especially if they will often use your app) dont like to loose time. Animation is great when it enhances user experience and doesn't cause a delay in workflow.
EDIT2: for scrolling to top (from current position) you can use:
[table setContentOffset:CGPointZero
animated:YES];
What I'm trying to do is call selectRowAtIndexPath in my searchResultsTableView. I am doing this in my viewWillAppear so that the row gets selected after it comes back from another view controller. In this simple example, I'm just asking it to go to row 2. What happens is that it briefly selects row 2 and then the selection goes away. Any ideas?
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// just select row 2 as a test
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:2 inSection:0];
[self.searchController.searchResultsTableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[self.searchController.searchResultsTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
}
Thanks
Maybe you should call it in viewDidAppear:, so it's selected once the view is present, and not just before it's presented. The superclass of your controller might deselect all rows on viewDidAppear: (I'm not sure of that, though).
Also, I think you can do those two lines in just one:
[self.searchController.searchResultsTableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionTop];
Just go with viewDidLoad or viewDidAppear, and just use the single line told by EmilioPelaez.
I have a UITableView which is added to a view as a subview. When selecting a row a new view will be present with pushViewController: and the user has the option to push a Back-button to go back to the UITableView but then the cell is still selected.
Is there a way to deselect this when the view appears?
I have read that I should use the following code but I can't get it working. No errors, no warnings, no nothing.
[tableProgram deselectRowAtIndexPath:[tableProgram indexPathForSelectedRow] animated:NO];
You should deselect the row in the didSelectRowAtIndextPath method of the delegate of your UITableView. It should look something like this.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
/* initialize your view controller here v and then push it */
SomeViewController *v = [[[SomeViewController alloc] init] autorelease];
[self.navigationController pushViewController:v animated:YES];
}
Dot confuse it with didDeselectRowAtIndextPath method - it happens as people do not pay much attention when selecting methods from intelisense.
Another place you can use this is inside viewDidAppear
- (void)viewDidAppear:(BOOL)animated
and insert the following
NSIndexPath *indexPath = [tableView indexPathForSelectedRow];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
The cell stays selected after clicked and pushed to a different view controller, but deselects when it pops back to the original view controller, so it gives the user a visual cue for the last selected row.
quote SimonBS:
tried that and hoped it would work (to
get the animation) but it seems that
both viewDidAppear:(BOOL)animated and
viewWillAppear:(BOOL)animated aren't
called when in a subview.
the code by honcheng does work
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSIndexPath *indexPath = [self.tableViewOutlet indexPathForSelectedRow];
[self.tableViewOutlet deselectRowAtIndexPath:indexPath animated:YES];
}
you just need to use it on the TableView's superview. (For instance: if you have a xib file with a TableView subview inside the view you just need to go to the corresponding view controller code and override viewWillAppear, i just did it and it works! hello visual cue!)