How to navigate through textfields (Next / Done Bu

2018-12-31 20:47发布

How can I navigate through all my text fields with the "Next" Button on the iPhone Keyboard?

The last text field should close the Keyboard.

I've setup the IB the Buttons (Next / Done) but now I'm stuck.

I implemented the textFieldShouldReturn action but now the Next and Done Buttons close the Keyboard.

30条回答
只靠听说
2楼-- · 2018-12-31 21:26

I had about 10+ UITextField in my story board and the way I enabled next functionality was by creating an array of UITextField and making the next UITextField the firstResponder. Here's the implementation file:

#import "RegistrationTableViewController.h"

@interface RegistrationTableViewController ()
@property (weak, nonatomic) IBOutlet UITextField *fullNameTextField;
@property (weak, nonatomic) IBOutlet UITextField *addressTextField;
@property (weak, nonatomic) IBOutlet UITextField *address2TextField;
@property (weak, nonatomic) IBOutlet UITextField *cityTextField;
@property (weak, nonatomic) IBOutlet UITextField *zipCodeTextField;
@property (weak, nonatomic) IBOutlet UITextField *urlTextField;
@property (weak, nonatomic) IBOutlet UITextField *usernameTextField;
@property (weak, nonatomic) IBOutlet UITextField *emailTextField;
@property (weak, nonatomic) IBOutlet UITextField *passwordTextField;
@property (weak, nonatomic) IBOutlet UITextField *confirmPWTextField;

@end
NSArray *uiTextFieldArray;
@implementation RegistrationTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"view did load");
    uiTextFieldArray = @[self.fullNameTextField,self.addressTextField,self.address2TextField,self.cityTextField,self.zipCodeTextField,self.urlTextField,self.usernameTextField,self.emailTextField,self.passwordTextField,self.confirmPWTextField];
    for(UITextField *myField in uiTextFieldArray){
        myField.delegate = self;
    }


}
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
    long index = [uiTextFieldArray indexOfObject:textField];
    NSLog(@"%ld",index);
    if(index < (uiTextFieldArray.count - 1)){
        [uiTextFieldArray[++index] becomeFirstResponder];
    }else{
        [uiTextFieldArray[index] resignFirstResponder];
    }
    return YES;
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
查看更多
墨雨无痕
3楼-- · 2018-12-31 21:27

This worked for me in Xamarin.iOS / Monotouch. Change the keyboard button to Next, pass the control to the next UITextField and hide the keyboard after the last UITextField.

private void SetShouldReturnDelegates(IEnumerable<UIView> subViewsToScout )
{
  foreach (var item in subViewsToScout.Where(item => item.GetType() == typeof (UITextField)))
  {
    (item as UITextField).ReturnKeyType = UIReturnKeyType.Next;
    (item as UITextField).ShouldReturn += (textField) =>
    {
        nint nextTag = textField.Tag + 1;
        var nextResponder = textField.Superview.ViewWithTag(nextTag);
        if (null != nextResponder)
            nextResponder.BecomeFirstResponder();
        else
            textField.Superview.EndEditing(true); 
            //You could also use textField.ResignFirstResponder(); 

        return false; // We do not want UITextField to insert line-breaks.
    };
  }
}

Inside the ViewDidLoad you'll have:

If your TextFields haven't a Tag set it now:

txtField1.Tag = 0;
txtField2.Tag = 1;
txtField3.Tag = 2;
//...

and just the call

SetShouldReturnDelegates(yourViewWithTxtFields.Subviews.ToList());
//If you are not sure of which view contains your fields you can also call it in a safer way:
SetShouldReturnDelegates(txtField1.Superview.Subviews.ToList());
//You can also reuse the same method with different containerViews in case your UITextField are under different views.
查看更多
时光乱了年华
4楼-- · 2018-12-31 21:28

I have tried many codes and finally, this worked for me in Swift 3.0 Latest [March 2017]

The ViewController class should be inherited the UITextFieldDelegate for making this code working.

class ViewController: UIViewController,UITextFieldDelegate  

Add the Text field with the Proper Tag number and this tag number is used to take the control to appropriate text field based on incremental tag number assigned to it.

override func viewDidLoad() {
    userNameTextField.delegate = self
    userNameTextField.tag = 0
    userNameTextField.returnKeyType = UIReturnKeyType.next
    passwordTextField.delegate = self
    passwordTextField.tag = 1
    passwordTextField.returnKeyType = UIReturnKeyType.go
}

In the above code, the returnKeyType = UIReturnKeyType.next where will make the Key pad return key to display as Next you also have other options as Join/Go etc, based on your application change the values.

This textFieldShouldReturn is a method of UITextFieldDelegate controlled and here we have next field selection based on the Tag value incrementation

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField {
        nextField.becomeFirstResponder()
    } else {
        textField.resignFirstResponder()
        return true;
    }
    return false
 }
查看更多
听够珍惜
5楼-- · 2018-12-31 21:28

This is an old post, but has a high page rank so I'll chime in with my solution.

I had a similar issue and ended up creating a subclass of UIToolbar to manage the next/previous/done functionality in a dynamic tableView with sections: https://github.com/jday001/DataEntryToolbar

You set the toolbar as inputAccessoryView of your text fields and add them to its dictionary. This allows you to cycle through them forwards and backwards, even with dynamic content. There are delegate methods if you want to trigger your own functionality when textField navigation happens, but you don't have to deal with managing any tags or first responder status.

There are code snippets & an example app at the GitHub link to help with the implementation details. You will need your own data model to keep track of the values inside the fields.

查看更多
残风、尘缘若梦
6楼-- · 2018-12-31 21:29

I tried to solve this problem using a more sophisticated approach based on assigning each cell (or UITextField) in a UITableView a unique tag value that can be later retrieved: activate-next-uitextfield-in-uitableview-ios

I hope this helps!

查看更多
不流泪的眼
7楼-- · 2018-12-31 21:30

I like the OO solutions that have already been suggested by Anth0 and Answerbot. However, I was working on a quick and small POC, so I didn't want to clutter things with subclasses and categories.

Another simple solution is to create an NSArray of fields and lookup the next field when you press next. Not an OO solution, but quick, simple, and easy to implement. Also, you can see and modify the ordering at a glance.

Here's my code (built upon other answers in this thread):

@property (nonatomic) NSArray *fieldArray;

- (void)viewDidLoad {
    [super viewDidLoad];

    fieldArray = [NSArray arrayWithObjects: firstField, secondField, thirdField, nil];
}

- (BOOL) textFieldShouldReturn:(UITextField *) textField {
    BOOL didResign = [textField resignFirstResponder];
    if (!didResign) return NO;

    NSUInteger index = [self.fieldArray indexOfObject:textField];
    if (index == NSNotFound || index + 1 == fieldArray.count) return NO;

    id nextField = [fieldArray objectAtIndex:index + 1];
    activeField = nextField;
    [nextField becomeFirstResponder];

    return NO;
}
  • I always return NO because I don't want a line break inserted. Just thought I'd point that out since when I returned YES it would automatically exit the subsequent fields or insert a line break in my TextView. It took me a bit of time to figure that out.
  • activeField keeps track of the active field in case scrolling is necessary to unobscure the field from the keyboard. If you have similar code, make sure you assign the activeField before changing the first responder. Changing first responder is immediate and will fire the KeyboardWasShown event immediately.
查看更多
登录 后发表回答