我如何通过iPhone键盘上的“下一步”按钮浏览所有的文本字段?
最后一个文本字段应该关闭键盘。
我已经设置了IB按钮(下一步/完成),但现在我卡住了。
我实现了textFieldShouldReturn动作,但现在下一步和完成按钮关闭键盘。
我如何通过iPhone键盘上的“下一步”按钮浏览所有的文本字段?
最后一个文本字段应该关闭键盘。
我已经设置了IB按钮(下一步/完成),但现在我卡住了。
我实现了textFieldShouldReturn动作,但现在下一步和完成按钮关闭键盘。
当前回答
我在我的故事板中有大约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];
}
}
我用Michael G. Emmons的答案已经有一年了,效果很好。我最近注意到,立即调用resignFirstResponder,然后立即调用becomeFirstResponder会导致键盘“故障”,消失,然后立即出现。我稍微改变了他的版本,跳过resignFirstResponder如果nextField是可用的。
- (BOOL)textFieldShouldReturn:(UITextField *)textField { if ([textField isKindOfClass:[NRTextField class]]) { NRTextField *nText = (NRTextField*)textField; if ([nText nextField] != nil){ dispatch_async(dispatch_get_main_queue(), ^ { [[nText nextField] becomeFirstResponder]; }); } else{ [textField resignFirstResponder]; } } else{ [textField resignFirstResponder]; } return true; }
我尝试使用一种更复杂的方法来解决这个问题,该方法基于为UITableView中的每个单元格(或UITextField)分配一个稍后可以检索的唯一标签值: activate-next-uitextfield-in-uitableview-ios
我希望这能有所帮助!
下面是一个没有授权的例子:
tf1.addTarget(tf2, action: #selector(becomeFirstResponder), for: .editingDidEndOnExit)
tf2.addTarget(tf3, action: #selector(becomeFirstResponder), for: .editingDidEndOnExit)
ObjC:
[tf1 addTarget:tf2 action:@selector(becomeFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
[tf2 addTarget:tf3 action:@selector(becomeFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
使用UIControlEventEditingDidEndOnExit UITextField动作工作(大部分是未知的)。
您还可以很容易地将其连接到故事板中,因此不需要委托或代码。
编辑:实际上我不知道如何在故事板中连接这个。becomeFirstResponder似乎不是这个control-event的一个提供的动作,这是一个遗憾。尽管如此,你可以将所有的文本字段连接到你的ViewController中的一个动作,然后决定哪个textField成为基于发送者的firstresponder(虽然它不像上面的编程解决方案那么优雅,所以IMO用viewDidLoad中的上述代码来做)。
我更喜欢:
@interface MyViewController : UIViewController
@property (nonatomic, retain) IBOutletCollection(UIView) NSArray *inputFields;
@end
在NIB文件中,我以所需的顺序将textFields钩子到这个inputFields数组中。之后,我做了一个简单的UITextField的索引测试,报告用户点击返回:
// for UITextField
-(BOOL)textFieldShouldReturn:(UITextField*)textField {
NSUInteger index = [_inputFields indexOfObject:textField];
index++;
if (index < _inputFields.count) {
UIView *v = [_inputFields objectAtIndex:index];
[v becomeFirstResponder];
}
return NO;
}
// for UITextView
-(BOOL)textView:(UITextView*)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString*)text {
if ([@"\n" isEqualToString:text]) {
NSUInteger index = [_inputFields indexOfObject:textView];
index++;
if (index < _inputFields.count) {
UIView *v = [_inputFields objectAtIndex:index];
[v becomeFirstResponder];
} else {
[self.view endEditing:YES];
}
return NO;
}
return YES;
}