I have problem with a long form in iOS. The form itself is done with a static table view. For the form I needed a toolbar with prev/next and done. In this project I added BSKeyboardControls, and I've allready done it myself in another project.
The toolbar works fine except when the next or previous textField/textView is out of sight. Then the focus on the former textField won't change and I'm still typing in this text field. When I now scroll manually and the targeted next textfield appears it magically becomes the first responder. This is of course not the expected behabier.
So I figured out I would have to scroll the table view to the respective fields before trying to set them as first responder. But I connot get this done.
I've tried to this with indexPathes
NSIndexPath *path = [self.tableView indexPathForCell:(UITableViewCell *)textField.superview.superview];
[self.tableView scrollToRowAtIndexPat:path atScrollPosition:UITableViewScrollPositionTop animated:YES];
Although the super-superview is a valid (and the right) table cell, the path returned is nil. I also tried some variations
CGPoint point = [self.tableView convertPoint:textField.frame.origin toView:self.tableView];
NSIndexPath *path = [self.tableView indexPathForRowAtPoint:point];
and other variations with rects and indexPathsForRowsInRect.
The only way is to manually keep track of the textFields cell indexPaths, but that is no suitable solution in this case.
Anybody has an idea of how to achieve scrolling to an out of sight textField in a tableView?
Edit:
As Justin Paulson requested the code of keyboardControlsPreviousNextPressed:
- (void)keyboardControlsPreviousNextPressed:(BSKeyboardControls *)controls withDirection:(KeyboardControlsDirection)direction andActiveTextField:(id)textField
{
NSIndexPath *path = [self.tableView indexPathForCell:(UITableViewCell *)((UIView *)textField).superview.superview];
NSLog(#"path %# for cell %#", path, ((UIView *)textField).superview.superview);
[self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES];
[textField becomeFirstResponder];
}
As I said according to the output of the log the path is nil, whereas the super-superview is the rught table view cell
Thanks for trying to help me, i've a solution myself. In my keyboardControlsPreviousNextPressed i have now
[self.tableView scrollRectToVisible:((UIView *)textField).superview.superview.frame animated:YES];
[textField becomeFirstResponder];
This solution seems to work quite well. The only problem i've encountered is that sometimes the newly focused textField is hidden by the keyboard, so the tableViewController doesn't adjusts itself automatically. You could additionally scroll the row to the top to circumvent this in most cases.
NSIndexPath *path = [self.tableView indexPathForCell:(UITableViewCell *)textField.superview.superview];
[self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES];
Related
I have a segment control with a table view. When user clicks segment control, then table view changes data source. I would like table to scroll to last position user had seen.
For example: user was in segment 1 and looking at table view line 3.
segment 1 | segment 2
line 3
line 4
line 5
Then user clicked segment 2 then clicked back to segment 1. I want table view scroll to line 3.
Code is as below. In viewDidAppear I have same code to get lastSavedRow and call scrollToRowAtIndexPath. When app gets loaded the scrolling works. However, in segmentValueChanged action it doesn't roll to correct position. In debugger I am sure the lastSavedRow has correct number.
- (IBAction) segmentVauleChanged : (id)sender
{
// remember row number before segment value changes
NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];
NSArray * sortedIndexPaths = [indexPaths sortedArrayUsingSelector:#selector(compare:)];
NSIndexPath *firstVisibleIndexPath = [sortedIndexPaths objectAtIndex:0];
// function to write row number and seg index to user default
[self saveScrollPositionInSegment: self.currentSegmentSelectedIndex row:firstVisibleIndexPath.row];
self.currentSegmentSelectedIndex = segmentController.selectedSegmentIndex;
[self.tableView reloadData];
// scroll to last saved position
int lastSavedRow = [self getScrollPositionInSegment:segmentController.selectedSegmentIndex];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:lastSavedRow inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
Does anyone have same problem? Many thanks in advance!
The lastSavedRow will on the top of the current tableview. I think there maybe something wrong with the dealing with datasource. Maybe after change the datasource, the last postion the user seen was not the index you figured out!
If you provide more information or your example, we can help you to find out the mistake.
I would do the following.
1 .Call visibleCells before calling indexPathsForVisibleRows
[self.tableView visibleCells];
2.Look at the need for sorting the array before identifying firstVisibleIndexPath
3.reloadData is not synchronous so its possible that the table is not completed loading before you try to scroll to an index. So try to see if you can do the scrolling in one of the delegate functions instead of here. See this.
hackerinheels 's (3) is right. reloadData hasn't finished when scrolling table is called. So I added the code:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
if (section == ([self.tableView numberOfSections] - 1)) {
//NSLog(#"finish loading");
// put the scrolling table call here: [self scrollTableView ];
}
return nil;
}
Thank you all for helping!
all I am doing one chat application, i which i am using UITable view to display reply and response from user.in this case after some interval of time i am reloading my tableview to fetch new data from server. But the problem is that after adding new content to table view it will go at the bottom of table view and i have to scroll table view to see that one.or in other case whenever i am reloading my table it will show its first cell on view. Now my question is "is it possible to load last cell of UITableview after view gets load or reload table view?"
on search I find this line but it give me error
[sTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:sender.tag inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
what is sender.tag in this line? // use of undeclared identifier sender
This line working well but scrolling the page which i dont want
[table_readText scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES ];
Any idea or suggestion would be highly welcome.
Thanks in advance..
You can also look at the scroll view's setContentOffset:animated: method.
Going to the top would mean,
[self.tableView setContentOffset:CGPointZero animated:YES];
and the bottom would be,
CGFloat height = self.tableView.contentSize.height - self.tableView.bounds.size.height;
[self.tableView setContentOffset:CGPointMake(0, height) animated:YES];
SECOND option:
scrollToRowAtIndexPath:atScrollPosition:animated:
Scrolls the receiver until a row identified by index path is at a particular location on the screen.
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
How to scroll to a UIActionSheet cell where title is equal to a certain NSString value?
(I'm sure a tableview would be better etc... but this is what I have at the moment and need a solution for my current dilemma).
Could I use something like the following to scroll down to the row based on a certain NSString value when the actionsheet comes into view? If so how do I code the NSIndexPath indexPathForRow:row? I get undeclared identifier row at the moment.
[actionSheet scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
I'm able to get the title text of the action sheet row with:
actionSheetSelectedCity = [NSString stringWithFormat:#"%#",[actionSheet buttonTitleAtIndex: buttonIndex]];
I have a tableView in my view and all works fine, however each custom cell (ToDoListCell) has a text field which I allow users to edit, updating their data. All good and well, my problem occurs whenever trying to scroll to a cell which is going to be hidden by the keyboard.
Note: I adjust the size of the table using the NSNotificationCenter observer methods as the Apple documentation recommends and I know this is not the problem.
- (void)scrollToSelectedCell {
NSIndexPath *currentIndexPath = [NSIndexPath indexPathForItem:0 inSection:0];
while (currentIndexPath.row < self.todos.count) {
ToDoListCell *cell = (ToDoListCell *)[self.table cellForRowAtIndexPath:currentIndexPath];
if (cell.titleField.isEditing == YES) {
[self.table scrollToRowAtIndexPath:currentIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
break;
}
currentIndexPath = [NSIndexPath indexPathForItem:currentIndexPath.row + 1 inSection:0];
}
}
Any idea why it does not scroll to any cell which is not currently on screen?
Thanks,
Ben
Just a guess, but probably because
ToDoListCell *cell = (ToDoListCell *)[self.table cellForRowAtIndexPath:currentIndexPath];
is returning nil causing cell.titleField.isEditing == YES to always fail. So the scroll command is never called. Table views only hold onto visible cells, so if you've resized your table view such that the cell being edited is no longer visible, you're going probably going to get nil back. You need to determine the index path of the cell being edited before resizing the table.
If you are firing the code in response to a notification listener, are you firing the notification from the UI thread?
UI animations will not perform unless executed on the main thread.
dispatch_async(dispatch_get_main_thread(), ^{
// send notification
});
I feel like this is an issue that requires special attention... my Google-fu is pretty good but I haven't been able to get anything useful.
This is the simplest thing, and yet I can't seem to figure out what the problem is with it.
I have a UITableView. It's a subview that my VC calls _form. I'm using it for styling purposes, not really to display data. It has 2 cells.
On a certain event, I'm trying to select a different cell, using selectRowAtIndexPath:animated:scrollPosition.
When I do this, it SIGABRTS.
A simple example:
- (IBAction)submitClicked:(id)sender
{
[_submit setTitle:#"Wha!?" forState:UIControlStateNormal];
NSIndexPath *row = [NSIndexPath indexPathWithIndex:0];
NSLog(#"%d", [[_form indexPathForSelectedRow] row]);
[_form selectRowAtIndexPath:row animated:YES scrollPosition:YES];
}
The button's title is changed, AND the table prints that the selected row is 0 or 1, but on trying to select the desired cell, it breaks:
2012-03-09 21:57:39.905 <omitted>[16329:207] 0
2012-03-09 21:57:39.908 <omitted>[16329:207] *** Assertion failure in -[NSIndexPath row], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableViewSupport.m:2598
(gdb)
My assumption is that this implies something is wrong with how my table is configured, but I'm not sure what. Selecting the cells in the table normally (clicking it) is working, as indicated by the expected response in my tableView:didSelectRowAtIndexPath. Everything else works fine with how I have this set up, except this.
(Also, I other people replying with extra debug info, not just "(gdb)". How can I get this?)
Thanks!
An indexpath for a tableview cell needs to have both a row and a section. Try creating your index path using the factory method (defined in NSIndexPath UIKit Additions) like this instead:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[_form selectRowAtIndexPath:indexPath animated:YES scrollPosition:YES];