我如何通过iPhone键盘上的“下一步”按钮浏览所有的文本字段?
最后一个文本字段应该关闭键盘。
我已经设置了IB按钮(下一步/完成),但现在我卡住了。
我实现了textFieldShouldReturn动作,但现在下一步和完成按钮关闭键盘。
我如何通过iPhone键盘上的“下一步”按钮浏览所有的文本字段?
最后一个文本字段应该关闭键盘。
我已经设置了IB按钮(下一步/完成),但现在我卡住了。
我实现了textFieldShouldReturn动作,但现在下一步和完成按钮关闭键盘。
当前回答
if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; txt_Input = [[ UITextField alloc] initWithFrame:CGRectMake(0, 10, 150, 30)]; txt_Input.tag = indexPath.row+1; [self.array_Textfields addObject:txt_Input]; // Initialize mutable array in ViewDidLoad } -(BOOL)textFieldShouldReturn:(UITextField *)textField { int tag = ( int) textField.tag ; UITextField * txt = [ self.array_Textfields objectAtIndex:tag ] ; [ txt becomeFirstResponder] ; return YES ; }
其他回答
我更喜欢:
@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;
}
我很惊讶,这里有这么多答案没有理解一个简单的概念:在应用程序中的控件中导航不是视图本身应该做的事情。控制器的工作是决定将哪个控件作为下一个第一响应器。
此外,大多数答案只适用于前进导航,但用户也可能想后退。
这就是我想到的。表单应该由视图控制器管理,视图控制器是响应器链的一部分。所以你可以完全自由地实现以下方法:
#pragma mark - Key Commands
- (NSArray *)keyCommands
{
static NSArray *commands;
static dispatch_once_t once;
dispatch_once(&once, ^{
UIKeyCommand *const forward = [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:0 action:@selector(tabForward:)];
UIKeyCommand *const backward = [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:UIKeyModifierShift action:@selector(tabBackward:)];
commands = @[forward, backward];
});
return commands;
}
- (void)tabForward:(UIKeyCommand *)command
{
NSArray *const controls = self.controls;
UIResponder *firstResponder = nil;
for (UIResponder *const responder in controls) {
if (firstResponder != nil && responder.canBecomeFirstResponder) {
[responder becomeFirstResponder]; return;
}
else if (responder.isFirstResponder) {
firstResponder = responder;
}
}
[controls.firstObject becomeFirstResponder];
}
- (void)tabBackward:(UIKeyCommand *)command
{
NSArray *const controls = self.controls;
UIResponder *firstResponder = nil;
for (UIResponder *const responder in controls.reverseObjectEnumerator) {
if (firstResponder != nil && responder.canBecomeFirstResponder) {
[responder becomeFirstResponder]; return;
}
else if (responder.isFirstResponder) {
firstResponder = responder;
}
}
[controls.lastObject becomeFirstResponder];
}
额外的逻辑滚动屏幕外的响应可见之前可能适用。
这种方法的另一个优点是,您不需要子类化您可能想要显示的所有类型的控件(如UITextFields),而是可以在控制器级别管理逻辑,老实说,在控制器级别管理逻辑是正确的。
在Mac OS X的Cocoa中,你有下一个响应器链,在那里你可以询问文本字段下一个控件应该有焦点。这就是在文本字段之间进行标签操作的原因。但由于iOS设备没有键盘,只有触摸,所以这一概念没有在Cocoa touch的过渡中幸存下来。
这很容易做到,只要有两个假设:
所有“tabbable”UITextFields都在同一个父视图上。 它们的“制表符顺序”由tag属性定义。
假设你可以重写textFieldShouldReturn:如下:
-(BOOL)textFieldShouldReturn:(UITextField*)textField
{
NSInteger nextTag = textField.tag + 1;
// Try to find next responder
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
} else {
// Not found, so remove keyboard.
[textField resignFirstResponder];
}
return NO; // We do not want UITextField to insert line-breaks.
}
添加更多的代码,也可以忽略这些假设。
斯威夫特4.0
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let nextTag = textField.tag + 1
// Try to find next responder
let nextResponder = textField.superview?.viewWithTag(nextTag) as UIResponder!
if nextResponder != nil {
// Found next responder, so set it
nextResponder?.becomeFirstResponder()
} else {
// Not found, so remove keyboard
textField.resignFirstResponder()
}
return false
}
如果文本字段的superview是一个UITableViewCell那么下一个responder将是
let nextResponder = textField.superview?.superview?.superview?.viewWithTag(nextTag) as UIResponder!
你可以使用IQKeyboardManager库来做到这一点。它处理所有的事情,你不需要任何额外的设置。IQKeyboardManager可以通过CocoaPods获得,要安装它,只需在Podfile中添加以下行:
pod 'IQKeyboardManager'
或 只需拖放IQKeyBoardManager目录从演示项目到您的项目。就是这样。 IQKeyBoardManager目录可以从https://github.com/hackiftekhar/IQKeyboardManager找到
这是我对这个问题的解决方案。
为了解决这个问题(因为我讨厌依赖标签来做事情),我决定向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的链表,每一个都知道下一个是谁。
希望能有所帮助。