How to activate next UITextField in a UITableView?

14.7k views Asked by At

I am using this other SO answer for adding UITextFields to my UITableViewCells. However, I am now at a loss how I can let the user focus on the next item by using the next button. Any hints?

4

There are 4 answers

4
Anh On BEST ANSWER

Try assigning a tag to each UITextField. Once the Next button is pressed, calculate the next tag and use [[UIView viewWithTag:nextTag] becomeFirstResponder] to change the focus to the next text field.

0
rbbtsn0w On

Would do you like ..

NSArray *arrayCells = [self.aTableView visibleCells];

UITableViewCell * currentCell = (UITableViewCell *) textField.superview.superview;
NSIndexPath * currentIndexPath = [self.aTableView indexPathForCell:currentCell];

if ((currentIndexPath.row != [arrayCells count] - 1) && (currentIndexPath.row < [arrayCells count]-1)) {

    NSIndexPath * nextIndexPath = [NSIndexPath indexPathForRow:currentIndexPath.row + 1 inSection:0];
    UITableViewCell * nextCell = (UITableViewCell *) [self.aTableView cellForRowAtIndexPath:nextIndexPath];

    [self.aTableView scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];

    for (id object in nextCell.contentView.subviews) {
        if ([object isKindOfClass:[UITextField class]]) {
            UITextField *tf = object;
            [tf becomeFirstResponder];
        }
    }
3
Kenny Wyland On

In addition to what Anh posted about using the tag value to find the next field and make it firstResponder...

If you are in a UITableView, you also need to keep in mind that the next UITextField might not be on the screen or even in the view because it might be below the bottom of the screen. You might need to scroll that new row into view before making it first responder. What I did in a previous app to handle this was make the tag be a value that I could use to imply the NSIndexPath of the row so I could figure out which row it was in. Then you can scroll that row into view with:

[tableView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];

However, this creates a race condition where the cell isn't visible yet when you call becomeFirstResponder, so I would delay the becomeFirstResponder until it is visible. I would set a value as a property in my class, like the row number, of the field which was supposed to become first responder and then in either cellForRowAtIndexPath or willDisplayCell:forRowAtIndexPath when I'm about to display that cell I would call becomeFirstResponder on the textfield THEN... because then it is guaranteed to exist.

3
Alfie Hanssen On

This worked well for me, would have to be tweaked to fit your needs though:

#pragma mark - UITextField Delegate

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{
    HRCFormCell * currentCell = (HRCFormCell *) textField.superview.superview;
    NSIndexPath * currentIndexPath = [self.tableview indexPathForCell:currentCell];

    if (currentIndexPath.row != [self.questionsArray count] - 1) {

        NSIndexPath * nextIndexPath = [NSIndexPath indexPathForRow:currentIndexPath.row + 1 inSection:0];
        HRCFormCell * nextCell = (HRCFormCell *) [self.tableview cellForRowAtIndexPath:nextIndexPath];

        [self.tableview scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; 

        [nextCell.textField becomeFirstResponder];
    }

    return YES;
}