Answers:
在Mac OS X的Cocoa中,您具有下一个响应者链,您可以在其中询问文本字段接下来应关注的控件。这就是使文本字段之间的制表符起作用的原因。但是由于iOS设备没有键盘,只有触摸,所以这个概念在过渡到Cocoa Touch时还没有幸免。
无论如何,可以通过两个假设轻松完成此操作:
UITextField
都在同一父视图上。假设您可以覆盖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
}
如果文本字段的超级视图为UITableViewCell,则下一个响应者为
let nextResponder = textField.superview?.superview?.superview?.viewWithTag(nextTag) as UIResponder!
UITableViewCell
。您将需要访问关联的内容UITableView
并获取包含您要查找的文本字段的单元格。
UITextFieldDelegate
和设置文本字段委托。
还有一个很多更优雅的解决方案,它把我吓倒了,我第一次看到它。优点:
UITextField
和UITextView
控件-或任何键盘输入UI控件创建一个UITextField子类,该子类具有IBOutlet
名为nextField 的属性。这是标题:
@interface SOTextField : UITextField
@property (weak, nonatomic) IBOutlet UITextField *nextField;
@end
这是实现:
@implementation SOTextField
@end
在视图控制器中,您将创建-textFieldShouldReturn:
委托方法:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if ([textField isKindOfClass:[SOTextField class]]) {
UITextField *nextField = [(SOTextField *)textField nextField];
if (nextField) {
dispatch_async(dispatch_get_current_queue(), ^{
[nextField becomeFirstResponder];
});
}
else {
[textField resignFirstResponder];
}
}
return YES;
}
在IB中,将UITextFields更改为使用SOTextField
该类。接下来,同样在IB中,将每个'SOTextFields'的委托设置为'File's Owner'(在放置委托方法的代码-textFieldShouldReturn的正确位置)。这种设计的优点在于,现在您只需右键单击任何textField,并将nextField出口分配给SOTextField
您想要成为下一个响应者的下一个对象。
此外,您可以做一些很酷的事情,例如循环textFields,这样在最后一个失去焦点之后,第一个将再次获得焦点。
这可以很容易地扩展到自动分配returnKeyType
的SOTextField
一个UIReturnKeyNext
,如果有一个nextField分配-少了一个东西手动配置。
UITableView
。尽管我IBOutlet
在视图控制器上具有每个文本字段的nextField
属性,但不能让我将属性链接到“文件所有者”上的那些属性。有什么建议可以使它在这种情况下工作吗?
textField1.nextField = textField2; textField2.nextField = textField3;
等
这是一个没有授权的:
tf1.addTarget(tf2, action: #selector(becomeFirstResponder), for: .editingDidEndOnExit)
tf2.addTarget(tf3, action: #selector(becomeFirstResponder), for: .editingDidEndOnExit)
对象:
[tf1 addTarget:tf2 action:@selector(becomeFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
[tf2 addTarget:tf3 action:@selector(becomeFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
使用(几乎未知)UIControlEventEditingDidEndOnExit
UITextField
操作进行工作。
您也可以轻松地将其连接到情节提要中,因此不需要委派或代码。
编辑:实际上我不知道如何将其挂接到情节提要中。becomeFirstResponder
对于此控制事件,似乎不是提供的操作,这很可惜。不过,您仍然可以将所有文本字段都挂接到ViewController中的单个动作上,然后再becomeFirstResponder
根据发送者确定要发送的文本字段(尽管它不如上面的编程解决方案那么优雅,因此IMO使用中的上述代码进行了处理viewDidLoad
)。
[tfN addTarget:self action:@selector(loginButtonTapped:) forControlEvents:UIControlEventEditingDidEndOnExit];
。谢谢@mxcl。
这是我针对这个问题的解决方案。
为了解决这个问题(并且因为我讨厌依靠标签来完成工作),我决定向UITextField对象添加一个自定义属性。换句话说,我在UITextField上创建了一个类别,如下所示:
UITextField + Extended.h
@interface UITextField (Extended)
@property(retain, nonatomic)UITextField* nextTextField;
@end
UITextField + Extended.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的链接列表,每个列表都知道该行中的下一个。
希望能对您有所帮助。
一个快速扩展,使用mxcl的答案使其变得特别容易(适用于Traveler的swift 2.3):
extension UITextField {
class func connectFields(fields:[UITextField]) -> Void {
guard let last = fields.last else {
return
}
for i in 0 ..< fields.count - 1 {
fields[i].returnKeyType = .Next
fields[i].addTarget(fields[i+1], action: "becomeFirstResponder", forControlEvents: .EditingDidEndOnExit)
}
last.returnKeyType = .Done
last.addTarget(last, action: #selector(UIResponder.resignFirstResponder), forControlEvents: .EditingDidEndOnExit)
}
}
易于使用:
UITextField.connectFields([field1, field2, field3])
该扩展程序会将除最后一个字段以外的所有字段的返回按钮设置为“下一步”,对于最后一个字段将返回按钮设置为“完成”,并在点按这些键时移动焦点/关闭键盘。
斯威夫特<2.3
extension UITextField {
class func connectFields(fields:[UITextField]) -> Void {
guard let last = fields.last else {
return
}
for var i = 0; i < fields.count - 1; i += 1 {
fields[i].returnKeyType = .Next
fields[i].addTarget(fields[i+1], action: "becomeFirstResponder", forControlEvents: .EditingDidEndOnExit)
}
last.returnKeyType = .Done
last.addTarget(last, action: "resignFirstResponder", forControlEvents: .EditingDidEndOnExit)
}
}
SWIFT 3: 像这样使用-
UITextField.connectFields(fields: [field1, field2])
Extension:
extension UITextField {
class func connectFields(fields:[UITextField]) -> Void {
guard let last = fields.last else {
return
}
for i in 0 ..< fields.count - 1 {
fields[i].returnKeyType = .next
fields[i].addTarget(fields[i+1], action: #selector(UIResponder.becomeFirstResponder), for: .editingDidEndOnExit)
}
last.returnKeyType = .go
last.addTarget(last, action: #selector(UIResponder.resignFirstResponder), for: .editingDidEndOnExit)
}
}
UITextFieldDelegate
并实现即可func textFieldDidEndEditing(textField: UITextField)
。如果早点回来textField != field3
。
一种更一致,更健壮的方法是使用NextResponderTextField。
您可以完全从接口构建器对其进行配置,而无需设置委托或使用view.tag
。
您需要做的就是
UITextField
为NextResponderTextField
nextResponderField
为指向下一个响应者,它可以是UITextField
任何子UIResponder
类或任何子类。它也可以是UIButton,并且该库足够聪明,TouchUpInside
只有在启用按钮后才能触发按钮事件。
这是运行中的库:
我喜欢Anth0和Answerbot已经建议的OO解决方案。但是,我正在研究一个快速而小型的POC,所以我不想将子类和类别弄得一团糟。
另一个简单的解决方案是创建一个NSArray字段,并在按下next时查找下一个字段。不是OO解决方案,而是快速,简单且易于实现。此外,您可以一目了然地查看和修改顺序。
这是我的代码(基于该线程的其他答案):
@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;
}
这是在UIControl上使用类别进行制表的实现。此解决方案具有Michael和Anth0中方法的所有优点,但适用于所有UIControl,而不仅限于UITextField
s。它还可以与Interface Builder和情节提要无缝地配合使用。
源和示例应用程序:UIControlsWithTabbing的GitHub存储库
用法:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField transferFirstResponderToNextControl];
return NO;
}
标头:
//
// UIControl+NextControl.h
// UIControlsWithTabbing
//
#import <UIKit/UIKit.h>
@interface UIControl (NextControl)
@property (nonatomic, weak) IBOutlet UIControl *nextControl;
- (BOOL)transferFirstResponderToNextControl;
@end
实现方式:
#import "UIControl+NextControl.h"
#import <objc/runtime.h>
static char defaultHashKey;
@implementation UIControl (NextControl)
- (UIControl *)nextControl
{
return objc_getAssociatedObject(self, &defaultHashKey);
}
- (void)setNextControl:(UIControl *)nextControl
{
objc_setAssociatedObject(self, &defaultHashKey, nextControl, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)transferFirstResponderToNextControl
{
if (self.nextControl)
{
[self.nextControl becomeFirstResponder];
return YES;
}
[self resignFirstResponder];
return NO;
}
@end
我尝试了许多代码,最后,这在Swift 3.0 Latest [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.next
键盘返回键在何处显示,因为Next
您还有其他选择,例如Join/Go
根据您的应用程序更改值。
这 textFieldShouldReturn
是一种受UITextFieldDelegate控制的方法,这里我们基于Tag值的增量选择下一个字段
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
}
UITextView
。知道如何结合使用吗?
UITextField
(输入单行文本),另一种是UITextView
(输入多行文本)。UITextView
显然不响应此代码,但可以形式使用。
从一个文本字段退出后,调用[otherTextField成为FirstResponder],下一个字段将获得焦点。
实际上,这可能是一个棘手的问题,因为通常您还希望滚动屏幕或以其他方式调整文本字段的位置,以便在编辑时易于查看。只要确保对进入和离开文本字段的方式进行大量测试,并尽早离开(总是让用户可以选择关闭键盘,而不是转到下一个字段,通常使用“完成”导航栏)
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[[self.view viewWithTag:textField.tag+1] becomeFirstResponder];
return YES;
}
按下“完成”按钮时,关闭键盘的一种非常简单的方法是:
在标题中创建一个新的IBAction
- (IBAction)textFieldDoneEditing:(id)sender;
在实现文件(.m文件)中,添加以下方法:
- (IBAction)textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
}
然后,当您将IBAction链接到文本字段时-链接到“退出时结束结束”事件。
首先在xib中设置键盘返回键,否则您可以在中编写代码viewdidload
:
passWord.returnKeyType = UIReturnKeyNext;
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
if(textField == eMail) {
[textField resignFirstResponder];
[userName becomeFirstResponder];
}
if (textField==userName) {
[textField resignFirstResponder];
[passWord becomeFirstResponder];
}
if (textField==passWord) {
[textField resignFirstResponder];
[country becomeFirstResponder];
}
if (textField==country) {
[textField resignFirstResponder];
}
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];
}
可以使用滚动可见的屏幕外响应者的其他逻辑。
这种方法的另一个好处是,你并不需要继承各种控件,你可能想显示(如UITextField
S),但在控制器级别,其中,说实话可以代替管理逻辑,是在正确的地方这样做。
如果您要实现上一个/下一个按钮功能,我已经在PeyloW的答案中添加了:
- (IBAction)moveThroughTextFields:(UIBarButtonItem *)sender
{
NSInteger nextTag;
UITextView *currentTextField = [self.view findFirstResponderAndReturn];
if (currentTextField != nil) {
// I assigned tags to the buttons. 0 represent prev & 1 represents next
if (sender.tag == 0) {
nextTag = currentTextField.tag - 1;
} else if (sender.tag == 1) {
nextTag = currentTextField.tag + 1;
}
}
// Try to find next responder
UIResponder* nextResponder = [self.view viewWithTag:nextTag];
if (nextResponder) {
// Found next responder, so set it.
// I added the resign here in case there's different keyboards in place.
[currentTextField resignFirstResponder];
[nextResponder becomeFirstResponder];
} else {
// Not found, so remove keyboard.
[currentTextField resignFirstResponder];
}
}
像这样子类化UIView的地方:
@implementation UIView (FindAndReturnFirstResponder)
- (UITextView *)findFirstResponderAndReturn
{
for (UITextView *subView in self.subviews) {
if (subView.isFirstResponder){
return subView;
}
}
return nil;
}
@end
大家好,请看这一个
- (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;
}
}
我尝试使用基于分配每个单元格(或更复杂的方法来解决这个问题UITextField
的),UITableView
以后可以检索到一个独特的标记值:
activate-next-uitextfield-in-uitableview-ios
我希望这有帮助!
在处理GNTextFieldsCollectionManager时,我刚刚创建了新的Pod 。它会自动处理下一个/最后一个textField问题,并且非常易于使用:
[[GNTextFieldsCollectionManager alloc] initWithView:self.view];
获取所有出现在视图层次结构(或按标签)中的文本字段,或者您可以指定自己的textFields数组。
Swift 3.1中的解决方案,连接文本字段之后,IBOutlets在viewDidLoad中设置文本字段委托,然后在textFieldShouldReturn中导航操作
class YourViewController: UIViewController,UITextFieldDelegate {
@IBOutlet weak var passwordTextField: UITextField!
@IBOutlet weak var phoneTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.passwordTextField.delegate = self
self.phoneTextField.delegate = self
// Set your return type
self.phoneTextField.returnKeyType = .next
self.passwordTextField.returnKeyType = .done
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool{
if textField == self.phoneTextField {
self.passwordTextField.becomeFirstResponder()
}else if textField == self.passwordTextField{
// Call login api
self.login()
}
return true
}
}
如果有人想要这样。我认为这是最接近所要求的要求的
这是我实现此方法的方式
使用以下命令为要设置的每个文本字段添加附件视图
func setAccessoryViewFor(textField : UITextField) {
let toolBar = UIToolbar()
toolBar.barStyle = .default
toolBar.isTranslucent = true
toolBar.sizeToFit()
// Adds the buttons
// Add previousButton
let prevButton = UIBarButtonItem(title: "<", style: .plain, target: self, action: #selector(previousPressed(sender:)))
prevButton.tag = textField.tag
if getPreviousResponderFor(tag: textField.tag) == nil {
prevButton.isEnabled = false
}
// Add nextButton
let nextButton = UIBarButtonItem(title: ">", style: .plain, target: self, action: #selector(nextPressed(sender:)))
nextButton.tag = textField.tag
if getNextResponderFor(tag: textField.tag) == nil {
nextButton.title = "Done"
}
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
toolBar.setItems([prevButton,spaceButton,nextButton], animated: false)
toolBar.isUserInteractionEnabled = true
textField.inputAccessoryView = toolBar
}
使用以下功能处理水龙头
func nextPressed(sender : UIBarButtonItem) {
if let nextResponder = getNextResponderFor(tag: sender.tag) {
nextResponder.becomeFirstResponder()
} else {
self.view.endEditing(true)
}
}
func previousPressed(sender : UIBarButtonItem) {
if let previousResponder = getPreviousResponderFor(tag : sender.tag) {
previousResponder.becomeFirstResponder()
}
}
func getNextResponderFor(tag : Int) -> UITextField? {
return self.view.viewWithTag(tag + 1) as? UITextField
}
func getPreviousResponderFor(tag : Int) -> UITextField? {
return self.view.viewWithTag(tag - 1) as? UITextField
}
您需要按顺序让textFields标签,以使next / prev按钮响应。
我宁愿:
@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;
}
如果(cell == nil) { 单元格= [[UITableViewCell分配] initWithStyle:UITableViewCellStyleDefault重用标识符:cellIdentifier]; txt_Input = [[UITextField alloc] initWithFrame:CGRectMake(0,10,150,30)]; txt_Input.tag = indexPath.row + 1; [self.array_Textfields addObject:txt_Input]; //在ViewDidLoad中初始化可变数组 } -(BOOL)textFieldShouldReturn:(UITextField *)textField { int标签=(int)textField.tag; UITextField * txt = [self.array_Textfields objectAtIndex:tag]; [txt成为FirstResponder]; 返回YES; }
我的故事板上有大约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
这在Xamarin.iOS / Monotouch中为我工作。将键盘按钮更改为“下一步”,将控件传递给下一个UITextField,然后在最后一个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.
};
}
}
在ViewDidLoad中,您将拥有:
如果您的TextFields没有标签,请立即设置:
txtField1.Tag = 0;
txtField2.Tag = 1;
txtField3.Tag = 2;
//...
还有电话
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.
这是快速的简单解决方案,无需使用标签,也没有情节提要技巧...
只需使用此扩展名:
extension UITextField{
func nextTextFieldField() -> UITextField?{
//field to return
var returnField : UITextField?
if self.superview != nil{
//for each view in superview
for (_, view) in self.superview!.subviews.enumerate(){
//if subview is a text's field
if view.isKindOfClass(UITextField){
//cast curent view as text field
let currentTextField = view as! UITextField
//if text field is after the current one
if currentTextField.frame.origin.y > self.frame.origin.y{
//if there is no text field to return already
if returnField == nil {
//set as default return
returnField = currentTextField
}
//else if this this less far than the other
else if currentTextField.frame.origin.y < returnField!.frame.origin.y{
//this is the field to return
returnField = currentTextField
}
}
}
}
}
//end of the mdethod
return returnField
}
}
并使用您的文本字段委托这样调用(例如):
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
textField.nextTextFieldField()?.becomeFirstResponder()
return true
}
一种更安全,更直接的方法,假设:
Swift 4.1:
extension ViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let nextTag = textField.tag + 1
guard let nextTextField = textField.superview?.viewWithTag(nextTag) else {
textField.resignFirstResponder()
return false
}
nextTextField.becomeFirstResponder()
return false
}
}
这是旧文章,但是页面排名很高,因此我将尽我所能。
我有一个类似的问题,最终创建了一个子类UIToolbar
来管理带有部分的动态tableView中的next / previous / done功能:https : //github.com/jday001/DataEntryToolbar
您将工具栏设置为文本字段的inputAccessoryView并将其添加到其字典中。这样,即使是动态内容,您也可以前后循环浏览它们。如果您想在textField导航发生时触发自己的功能,则可以使用委托方法,但不必处理任何标签或第一响应者状态。
GitHub链接上有代码片段和示例应用程序,可帮助您实现详细信息。您将需要自己的数据模型来跟踪字段中的值。
在不使用标签且不为nextField / nextTextField添加属性的情况下,可以尝试使用此方法来模拟TAB,其中“ testInput”是当前的活动字段:
if ([textInput isFirstResponder])
[textInput.superview.subviews enumerateObjectsAtIndexes:
[NSIndexSet indexSetWithIndexesInRange:
NSMakeRange([textInput.superview.subviews indexOfObject:textInput]+1,
[textInput.superview.subviews count]-[textInput.superview.subviews indexOfObject:textInput]-1)]
options:0 usingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) {
*stop = !obj.hidden && [obj becomeFirstResponder];
}];
if ([textInput isFirstResponder])
[textInput.superview.subviews enumerateObjectsAtIndexes:
[NSIndexSet indexSetWithIndexesInRange:
NSMakeRange(0,
[textInput.superview.subviews indexOfObject:textInput])]
options:0 usingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) {
*stop = !obj.hidden && [obj becomeFirstResponder];
}];
我一直在使用Michael G. Emmons的答案大约一年了,效果很好。最近我确实注意到,调用resignFirstResponder然后立即成为FirstResponder会导致键盘“毛刺”,消失并立即出现。如果nextField可用,我略微更改了其版本以跳过resignFirstResponder。
-(BOOL)textFieldShouldReturn:(UITextField *)textField { 如果([textField isKindOfClass:[NRTextField class]]) { NRTextField * nText =(NRTextField *)textField; 如果([nText nextField]!= nil){ dispatch_async(dispatch_get_main_queue(), ^ {[[nText nextField]成为FirstResponder]; }); } 其他{ [textField resignFirstResponder]; } } 其他{ [textField resignFirstResponder]; } 返回true; }