我有一个iPad应用程序,其中包含一个注册表单。该表单非常基础,只包含两个UITextFields,分别用于姓名和电子邮件地址。
第一个TextField是候选人姓名,当他们输入姓名并按下键盘上的“下一个”时,我希望自动跳转到下一个电子邮件地址TextField进行编辑。
有什么办法可以将键盘上的下一个按钮设置为跳转到下一个键盘吗?
谢谢
我有一个iPad应用程序,其中包含一个注册表单。该表单非常基础,只包含两个UITextFields,分别用于姓名和电子邮件地址。
第一个TextField是候选人姓名,当他们输入姓名并按下键盘上的“下一个”时,我希望自动跳转到下一个电子邮件地址TextField进行编辑。
有什么办法可以将键盘上的下一个按钮设置为跳转到下一个键盘吗?
谢谢
您需要将您的视图控制器设置为UITextField的代理,并实现UITextField代理方法:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == nameField) {
[textField resignFirstResponder];
[emailField becomeFirstResponder];
} else if (textField == emailField) {
// here you can define what happens
// when user presses return on the email field
}
return YES;
}
Swift版本:
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField == nameField {
textField.resignFirstResponder()
emailField.becomeFirstResponder()
} else if textField == emailField {
// here you can define what happens
// when user presses return on the email field
}
return true
}
您可能还需要滚动视图以使emailField可见。 如果您的视图控制器是UITableViewController的实例,则应自动发生此操作。 如果不是,您应该阅读这份Apple文档,特别是移动位于键盘下方的内容部分。
除了 @lawicko 的回答外,我经常更改按钮文本以达到最后的完美效果(例如,在还有更多字段时显示“下一页”,在最后一个字段时显示“完成”):
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
BOOL isLastTextField = //.. your logic to figure out if the current text field is the last
if (isLastTextField) {
textField.returnKeyType = UIReturnKeyDone;
} else {
textField.returnKeyType = UIReturnKeyNext;
}
}
Swift版本的正确答案。
根据我的经验,在切换文本字段时不需要调用resignFirstResponder。
在这个例子中,只有基本的用户名和密码文本字段。
Storyboard中用户名的键盘“return key”设置为“下一个”,密码的设置为“完成”。
然后只需连接这两个文本字段的代理并添加此扩展即可。
extension LoginViewController: UITextFieldDelegate {
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField == textFieldPassword {
self.view.endEditing(true)
} else {
textFieldPassword.becomeFirstResponder()
}
return true
}
}
一个 Swift 4 的拓展。只需传入 UITextFields
数组,它将把每个文本框连接到下一个,直到最后一个文本框放弃第一响应者(隐藏键盘):
extension UITextField {
class func connectFields(fields: [UITextField]) {
guard let last = fields.last else { return }
// To reset the targets in case you call this method again to change the connected fields
fields.forEach { $0.removeTarget(nil, action: nil, for: .editingDidEndOnExit) }
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 = .continue
last.addTarget(last, action: #selector(UIResponder.resignFirstResponder), for: .editingDidEndOnExit)
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField.allControlEvents.contains(.editingDidEndOnExit) {
textField.sendActions(for: .editingDidEndOnExit)
return false
} else {
textField.resignFirstResponder()
return true
}
}
} - Michał ZiobroUITextField
的类类型设置为NextResponderTextField
。
nextResponderField
的输出口指向下一个响应器,它可以是任何UITextField
或任何UIResponder
子类。它还可以是一个UIButton,如果启用,则库足够智能,只会触发按钮的TouchUpInside
事件。
viewController.h
(IBAction)textFieldDoneEditing:(id)sender;
viewController.m
(IBAction)textFieldDoneEditing:(id)sender {
[textField resignFirstResponder];
if (textField == nameField) {
[emailField becomeFirstResponder];
}
}
建立(show the connections inspector > Sent Events)didEndOnExit和textFieldDoneEditing之间的关联
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.textFieldName)
{
[self.textFieldName resignFirstResponder];
[self.textFieldPassword becomeFirstResponder];
}
else if (textField == self.textFieldPassword)
{
[self.textFieldPassword resignFirstResponder];
[self login:self];
}
return true;
}
@interface MLLoginViewController ()<UITextFieldDelegate>
@end
@implementation MLLoginViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.textFieldName.delegate = self;
self.textFieldPassword.delegate = self;
[textField resignFirstResponder];
并不重要。只要表单中还有其他字段,就将becomeFirstResponder
移到下一个字段:[emailField becomeFirstResponder];
- MalloctextField
不是UITextField
的子类并且在第一响应者状态被放弃时不执行任何特定操作的简单情况来说,你是正确的。然而,我的代码适用于所有情况,包括更复杂的情况。请参见此处了解为什么可能需要重写resignFirstResponder
。 - lawicko