我如何通过iPhone键盘上的“下一步”按钮浏览所有的文本字段?

最后一个文本字段应该关闭键盘。

我已经设置了IB按钮(下一步/完成),但现在我卡住了。

我实现了textFieldShouldReturn动作,但现在下一步和完成按钮关闭键盘。


当前回答

大家好,请看这个

- (void)nextPrevious:(id)sender
{

  UIView *responder = [self.view findFirstResponder];   

  if (nil == responder || ![responder isKindOfClass:[GroupTextField class]]) {
    return;
  }

  switch([(UISegmentedControl *)sender selectedSegmentIndex]) {
    case 0:
      // previous
      if (nil != ((GroupTextField *)responder).previousControl) {
        [((GroupTextField *)responder).previousControl becomeFirstResponder];
        DebugLog(@"currentControl: %i previousControl: %i",((GroupTextField *)responder).tag,((GroupTextField *)responder).previousControl.tag);
      }
      break;
    case 1:
      // next
      if (nil != ((GroupTextField *)responder).nextControl) {
        [((GroupTextField *)responder).nextControl becomeFirstResponder];
        DebugLog(@"currentControl: %i nextControl: %i",((GroupTextField *)responder).tag,((GroupTextField *)responder).nextControl.tag);
      }     
      break;    
  }
}

其他回答

我尝试了很多代码,最后,这在Swift 3.0最新版[2017年3月]对我有效

ViewController类应该继承UITextFieldDelegate以使这段代码正常工作。

class ViewController: UIViewController,UITextFieldDelegate  

使用适当的标记号添加文本字段,该标记号用于根据分配给它的增量标记号将控件转移到适当的文本字段。

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

在上面的代码中,returnKeyType = UIReturnKeyType。下一个将使键垫返回键显示为下一个你也有其他选项加入/走等,根据你的应用程序改变值。

这个textFieldShouldReturn是一个UITextFieldDelegate控制的方法,在这里我们有下一个字段选择基于标签值的增量

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
 }

这是我对这个问题的解决方案。

为了解决这个问题(因为我讨厌依赖标签来做事情),我决定向UITextField对象添加一个自定义属性。换句话说,我在UITextField上创建了一个这样的类别:

UITextField + Extended.h

@interface UITextField (Extended)

@property(retain, nonatomic)UITextField* nextTextField;

@end

UITextField +扩展。m

#import "UITextField+Extended.h"
#import <objc/runtime.h>

static char defaultHashKey;

@implementation UITextField (Extended)

- (UITextField*) nextTextField { 
    return objc_getAssociatedObject(self, &defaultHashKey); 
}

- (void) setNextTextField:(UITextField *)nextTextField{
    objc_setAssociatedObject(self, &defaultHashKey, nextTextField, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
}

@end

下面是我如何使用它:

UITextField *textField1 = ...init your textfield
UITextField *textField2 = ...init your textfield
UITextField *textField3 = ...init your textfield

textField1.nextTextField = textField2;
textField2.nextTextField = textField3;
textField3.nextTextField = nil;

实现textFieldShouldReturn方法:

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {

    UITextField *next = theTextField.nextTextField;
    if (next) {
        [next becomeFirstResponder];
    } else {
        [theTextField resignFirstResponder];
    }

    return NO; 
}

我现在有一个UITextField的链表,每一个都知道下一个是谁。

希望能有所帮助。

我在我的故事板中有大约10+ UITextField,我启用下一个功能的方式是通过创建一个UITextField数组,并使下一个UITextField成为firstResponder。下面是实现文件:

#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

我已经实现了在视图层次结构中通过Responders导航的动态解决方案。其思想是,在整个层次结构中搜索下一个可能的响应器,根据需要向前或向后搜索。

UIView搜索扩展:

UIView+Cat.h

- (UIResponder *)getNextFirstResponder;
- (UIResponder *)getPreviousFirstResponder;

UIView+Cat.m

- (UIResponder *)getPreviousFirstResponder {
    if (!self.superview) {
        return nil;
    }
    
    BOOL hasreachedself = NO;
    for (NSInteger i = self.superview.subviews.count-1; i >= 0; i--) {
        UIView *v = [self.superview.subviews objectAtIndex:i];
        if (v == self) {
            hasreachedself = YES;
            continue;
        }
        if (!hasreachedself) continue;
        
        if ([v canBecomeFirstResponder] && !v.hidden) {
            return v;
        }
        UIResponder *subResponder = [self getNextFirstResponderInView:v];
        if (subResponder) {
            return subResponder;
        }
    }
    
    //search hierachicaly in superviews
    return [self.superview getPreviousFirstResponder];
}

- (UIResponder *)getNextFirstResponder {
    if (!self.superview) {
        return nil;
    }
    
    BOOL hasreachedself = NO;
    for (UIView *v in self.superview.subviews) {
        if (v == self) {
            hasreachedself = YES;
            continue;
        }
        if (!hasreachedself) continue;
        
        if ([v canBecomeFirstResponder] && !v.hidden) {
            return v;
        }
        UIResponder *subResponder = [self getNextFirstResponderInView:v];
        if (subResponder) {
            return subResponder;
        }
    }
    
    //search hierachicaly in superviews
    return [self.superview getNextFirstResponder];
}

- (UIResponder *)getNextFirstResponderInView:(UIView *)view {
    if ([view canBecomeFirstResponder] && !view.hidden) {
        return view;
    }
    for (UIView *v in view.subviews) {
        UIResponder *subResponder = [self getNextFirstResponderInView:v];
        if (subResponder) {
            return subResponder;
        }
    }
    return nil;
}

用法:添加UIToolbar到UITextField / UITextView(在类别或子类中):

- (void)addToolbarInputAccessoryView {
    UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectZero];
    UIBarButtonItem *prev = [[UIBarButtonItem alloc] initWithImage:[UIImage systemImageNamed:@"chevron.up"] style:UIBarButtonItemStylePlain target:self action:@selector(moveToPreviousFirstResponder)];
    UIBarButtonItem *next = [[UIBarButtonItem alloc] initWithImage:[UIImage systemImageNamed:@"chevron.down"] style:UIBarButtonItemStylePlain target:self action:@selector(moveToNextFirstResponder)];
    UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(hideKeyboard)];
    toolbar.items = @[prev, next, space, done];
    
    if ([[UITextField appearance] keyboardAppearance] == UIKeyboardAppearanceDark) {
        toolbar.barStyle = UIBarStyleBlack;
        toolbar.translucent = YES;
        [toolbar setBarTintColor:[UIColor blackColor]];
        [toolbar setTintColor:[UIColor whiteColor]];
    }
    
    [toolbar sizeToFit];
    
    self.inputAccessoryView = toolbar;
}

- (void)hideKeyboard {
    [self resignFirstResponder];
}

- (void)moveToNextFirstResponder {
    UIResponder *next = [self getNextFirstResponder];
    if (next) {
        [next becomeFirstResponder];
    }
    else {
        [self resignFirstResponder];
    }
}

- (void)moveToPreviousFirstResponder {
    UIResponder *prev = [self getPreviousFirstResponder];
    if (prev) {
        [prev becomeFirstResponder];
    }
    else {
        [self resignFirstResponder];
    }
}

这是一个老帖子,但有一个很高的页面排名,所以我将附和我的解决方案。

我有一个类似的问题,最终创建了UIToolbar的子类来管理动态tableView中的下一个/前一个/完成功能:https://github.com/jday001/DataEntryToolbar

您将工具栏设置为文本字段的inputAccessoryView,并将它们添加到它的字典中。这允许您向前和向后循环浏览它们,即使是动态内容。有委托方法,如果你想触发你自己的功能时textField导航发生,但你不必处理管理任何标签或第一个响应器状态。

在GitHub链接中有代码片段和示例应用程序,以帮助实现细节。您需要自己的数据模型来跟踪字段中的值。