在Cocoa for Mac OS X中,您有下一个响应者链,您可以在其中询问文本字段接下来应该关注哪个控件 . 这就是使文本字段之间的标签工作的原因 . 但由于iOS设备没有键盘,只有触摸,这个概念还没有幸免于过渡到Cocoa Touch .
无论如何,这可以轻松完成,有两个假设:
所有"tabbable" UITextField s位于同一父视图中 .
他们的"tab-order"由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.
}
添加更多代码,也可以忽略这些假设 .
Swift 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
}
If the superview of the text field will be a UITableViewCell then next responder will be
let nextResponder = textField.superview?.superview?.superview?.viewWithTag(nextTag) as UIResponder!
- (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
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
这是一个简单的快速解决方案,没有标签使用,没有故事板技巧......
只需使用此扩展程序:
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
}
}
extension UIViewController: UITextFieldDelegate {
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
guard let next = textField.nextTextField else {
textField.resignFirstResponder()
return true
}
next.becomeFirstResponder()
return false
}
}
然后在你的ViewController或任何地方,你可以像这样设置你的文本域...
@IBOutlet fileprivate weak var textfield1: UITextField!
@IBOutlet fileprivate weak var textfield2: UITextField!
@IBOutlet fileprivate weak var textfield3: UITextField!
...
[textfield1, textfield2, textfield3].forEach{ $0?.delegate = self }
textfield1.nextTextField = textfield2
textfield2.nextTextField = textfield3
// We don't assign a nextTextField to textfield3 because we want
// textfield3 to be the last one and resignFirstResponder when
// the return button on the soft keyboard is tapped.
30 回答
在Cocoa for Mac OS X中,您有下一个响应者链,您可以在其中询问文本字段接下来应该关注哪个控件 . 这就是使文本字段之间的标签工作的原因 . 但由于iOS设备没有键盘,只有触摸,这个概念还没有幸免于过渡到Cocoa Touch .
无论如何,这可以轻松完成,有两个假设:
所有"tabbable"
UITextField
s位于同一父视图中 .他们的"tab-order"由tag属性定义 .
假设你可以覆盖textFieldShouldReturn:如下:
添加更多代码,也可以忽略这些假设 .
Swift 4.0
If the superview of the text field will be a UITableViewCell then next responder will be
有一个更优雅的解决方案,在我第一次看到它时就把我吹走了 . 优点:
更接近OSX文本字段实现,其中文本字段知道下一个焦点的位置
不依赖于设置或使用标签 - 这对于此用例来说是IMO脆弱的
可以扩展为与
UITextField
和UITextView
控件一起使用 - 或任何键盘输入UI控件不会使用样板文件UITextField委托代码来混淆视图控制器
与IB很好地集成,可以通过熟悉的选项 - 拖放来配置连接插座 .
创建一个UITextField子类,它具有名为nextField的
IBOutlet
属性 . 这是 Headers :这是实施:
在视图控制器中,您将创建
-textFieldShouldReturn:
委托方法:在IB中,更改您的UITextField以使用
SOTextField
类 . 接下来,同样在IB中,为每个'SOTextFields'设置委托给'File''所有者'(这是您放置委托方法代码的地方 - textFieldShouldReturn) . 这种设计的优点在于,现在您只需右键单击任何textField,并将nextField出口分配给您希望成为下一个响应者的下一个SOTextField
对象 .此外,你可以做很酷的事情,比如循环textFields,这样在最后一个失去焦点后,第一个会再次获得焦点 .
如果分配了nextField,则可以轻松扩展为自动将
的
returnKeyType
分配给UIReturnKeyNext
- 少一点手动配置 .这是我解决这个问题的方法 .
为了解决这个问题(因为我讨厌依赖标签来做东西),我决定在UITextField对象中添加一个自定义属性 . 换句话说,我在UITextField上创建了一个类别,如下所示:
UITextField+Extended.h
UITextField+Extended.m
现在,这是我如何使用它:
并实现textFieldShouldReturn方法:
我现在有一个UITextField的链接列表,每个人都知道谁在下一行 .
希望它会有所帮助 .
我刚刚在处理这些东西时创建了新的Pod GNTextFieldsCollectionManager . 它会自动处理下一个/最后一个textField问题,并且非常易于使用:
抓取按视图层次结构(或标记)显示的所有文本字段,或者您可以指定自己的textFields数组 .
这是一个没有代表团的人:
ObjC:
使用(主要是未知的)
UIControlEventEditingDidEndOnExit
UITextField
动作 .您还可以轻松地将其连接到故事板中,因此不需要委托或代码 .
编辑:实际上我无法弄清楚如何在故事板中将其连接起来 .
becomeFirstResponder
似乎不是这个控制事件的提供动作,这是一个遗憾 . 仍然,您可以将所有文本字段挂钩到ViewController中的单个操作,然后根据发件人确定哪个textField为becomeFirstResponder
(尽管它不像上面的程序化解决方案那样优雅,所以IMO使用viewDidLoad
中的上述代码执行此操作) .一个快速扩展,应用mxcl的答案,使这特别容易(适应旅行者swift 2.3):
它易于使用:
对于除最后一个字段之外的所有字段,扩展名将返回按钮设置为“下一个”,对于最后一个字段,将“返回”设置为“完成”,并在点击这些字段时切换焦点/关闭键盘 .
Swift < 2.3
SWIFT 3: 像这样使用 -
更一致和更健壮的方法是使用NextResponderTextField您可以完全从界面构建器配置它,而无需设置委托或使用
view.tag
.你需要做的就是
将
UITextField
的 class 类型设为NextResponderTextField
然后将
nextResponderField
的出口设置为指向下一个响应者,它可以是任何UITextField
或任何UIResponder
子类 . 它也可以是一个UIButton,并且该库足够智能,只有在启用时才会触发按钮的TouchUpInside
事件 .这是图书馆的行动:
我喜欢Anth0和Answerbot已经提出过的OO解决方案 . 但是,我正在开发一个快速小巧的POC,所以我不想让子类和类别混乱 .
另一个简单的解决方案是创建一个NSArray字段,并在按下下一个字段时查找下一个字段 . 不是OO解决方案,但快速,简单且易于实施 . 此外,您可以一目了然地查看和修改订购 .
这是我的代码(基于此线程中的其他答案):
我总是返回NO,因为我没有指出,因为当我返回YES时它将自动退出后续字段或在我的TextView中插入换行符 . 我花了一点时间才弄明白 .
activeField会跟踪活动字段,以防需要滚动以从键盘中取消显示字段 . 如果您有类似的代码,请确保在更改第一个响应者之前分配activeField . 立即更改第一响应者并立即触发KeyboardWasShown事件 .
这是使用UIControl上的类别进行Tab键的实现 . 这个解决方案具有Michael和Anth0方法的所有优点,但适用于所有UIControl,而不仅仅是
UITextField
. 它还可以与Interface Builder和故事板无缝协作 .来源和示例应用:GitHub repository for UIControlsWithTabbing
用法:
Headers :
执行:
退出一个文本字段后,调用[otherTextField becomeFirstResponder],下一个字段获得焦点 .
这实际上可能是一个棘手的问题,因为您通常还需要滚动屏幕或以其他方式调整文本字段的位置,以便在编辑时很容易看到 . 只需确保以不同的方式进出文本字段并进行大量测试,并提前离开(总是让用户选择关闭键盘而不是去下一个字段,通常使用“完成”导航栏)
我尝试了很多代码,最后,这对我有用_11244382_
ViewController
类应继承UITextFieldDelegate
以使此代码正常工作 .添加带有正确标记号的文本字段,此标记号用于根据分配给它的增量标记号将控件转移到适当的文本字段 .
在上面的代码中,
returnKeyType = UIReturnKeyType.next
where将使键盘返回键显示为Next
您还有其他选项Join/Go
等,根据您的应用程序更改值 .这个
textFieldShouldReturn
是一个UITextFieldDelegate控制的方法,这里我们根据Tag值增量进行下一个字段选择按下“完成”按钮时,解除键盘的一种非常简单的方法是:
在 Headers 中创建一个新的IBAction
在实现文件(.m文件)中添加以下方法:
然后,当您将IBAction链接到文本字段时 - 链接到“退出时结束”事件 .
我很惊讶这里有多少答案无法理解一个简单的概念:浏览应用程序中的控件并不是视图本身应该做的事情 . 确定下一个第一响应者的控制权是 controller 的工作 .
此外,大多数答案仅适用于向前导航,但用户可能也想要倒退 .
所以这就是我想出来的 . 您的表单应由视图控制器管理,视图控制器是响应程序链的一部分 . 所以你可以完全自由地实现以下方法:
可以应用用于预先滚动屏幕外响应者的附加逻辑 .
这种方法的另一个优点是你不需要子类化你可能想要显示的所有类型的控件(比如
UITextField
),而是可以在控制器级别管理逻辑,其中,说实话,是正确的地方所以 .首先在xib中设置键盘返回键,否则你可以在
viewdidload
中编写代码:我已经添加了PeyloW的答案,以防你想要实现上一个/下一个按钮功能:
你把UIView子类化的地方是这样的:
大家好,请看this one
我尝试使用更复杂的方法来解决这个问题,这种方法基于在_1124404中分配每个单元格(或
UITextField
),这是一个可以在以后检索的唯一标记值:activate-next-uitextfield-in-uitableview-ios我希望这有帮助!
Swift 3.1中的解决方案,在连接文本字段后,IBOutlets在viewDidLoad中设置文本字段委托,然后在textFieldShouldReturn中导航您的操作
我更喜欢:
在NIB文件中,我将textFields以所需顺序挂钩到此inputFields数组中 . 之后,我对UITextField的索引进行了简单测试,该索引报告用户点击了返回:
我的故事板上有大约10个UITextField,我启用下一个功能的方法是创建一个UITextField数组,并使下一个UITextField成为第一个响应者 . 这是实现文件:
这在Xamarin.iOS / Monotouch中适用于我 . 将键盘按钮更改为Next,将控件传递给下一个UITextField,并在最后一个UITextField之后隐藏键盘 .
在 ViewDidLoad 内你将拥有:
如果您的TextFields现在没有设置标签:
只是电话
这是一个简单的快速解决方案,没有标签使用,没有故事板技巧......
只需使用此扩展程序:
并使用您的textfield委托调用它(例如):
在textFieldShouldReturn中,你应该检查你当前所在的文本字段是不是最后一个,当他们点击下一个,如果它不要关闭键盘..
这是一个老帖子,但页面排名很高,所以我会使用我的解决方案 .
我遇到了类似的问题,并最终创建了一个
UIToolbar
的子类来管理动态tableView中的下一个/上一个/完成的功能,其中包含以下部分:https://github.com/jday001/DataEntryToolbar您将工具栏设置为文本字段的inputAccessoryView并将其添加到其字典中 . 这使您可以向前和向后循环,即使是动态内容也是如此 . 如果要在textField导航发生时触发自己的功能,则有委托方法,但您不必处理管理任何标记或第一响应者状态 .
GitHub链接中有代码片段和示例应用程序,以帮助实现详细信息 . 您将需要自己的数据模型来跟踪字段内的值 .
如果没有使用标签并且没有为nextField / nextTextField添加属性,您可以尝试使用它来模拟TAB,其中“testInput”是您当前的活动字段:
我一直在使用Michael G. Emmons的答案大约一年,效果很好 . 我最近注意到,调用resignFirstResponder然后立即调用FirstFirstResponder会导致键盘“出现故障”,消失然后立即出现 . 如果nextField可用,我稍微更改了他的版本以跳过resignFirstResponder .
您可以使用IQKeyboardManager库来执行此操作 . 它处理所有事情,你不需要任何额外的setup.IQKeyboardManager可以通过CocoaPods,安装它只需将以下行添加到你的Podfile:
或者只是将IQKeyBoardManager目录从演示项目拖放到您的项目中 . 而已 . 你可以在https://github.com/hackiftekhar/IQKeyboardManager找到IQKeyBoardManager目录
这是一个Swift 3版本的 Anth0 's answer. I' m在这里张贴,以帮助任何快速的开发人员想要利用他的好答案!当您设置关联对象时,我冒昧地添加了返回键类型"Next" .
这是另一个扩展,显示了使用上面的代码循环遍历UITextField列表的可能性 .
然后在你的ViewController或任何地方,你可以像这样设置你的文本域...