How to navigate through textfields (Next / Done Buttons)
How can I navigate through all my text fields with the "Next" Button on the iPhone Keyboard?
The last text field should close the Keyboard.
I've setup the IB the Buttons (Next / Done) but now I'm stuck.
I implemented the textFieldShouldReturn action but now the Next and Done Buttons close the Keyboard.
In Cocoa for Mac OS X, you have the next responder chain, where you can ask the text field what control should have focus next. This is what makes tabbing between text fields work. But since iOS devices do not have a keyboard, only touch, this concept has not survived the transition to Cocoa Touch.
This can be easily done anyway, with two assumptions:
UITextField
s are on the same parent view. Assuming this you can override textFieldShouldReturn: as this:
-(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.
}
Add some more code, and the assumptions can be ignored as well.
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!
There is a much more elegant solution which blew me away the first time I saw it. Benefits:
UITextField
and UITextView
controls -- or any keyboard entry UI control Create a UITextField subclass which has an IBOutlet
property called nextField. Here's the header:
@interface SOTextField : UITextField
@property (weak, nonatomic) IBOutlet UITextField *nextField;
@end
And here's the implementation:
@implementation SOTextField
@end
In your view controller, you'll create the -textFieldShouldReturn:
delegate method:
- (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;
}
In IB, change your UITextFields to use the SOTextField
class. Next, also in IB, set the delegate for each of the 'SOTextFields'to 'File's Owner' (which is right where you put the code for the delegate method - textFieldShouldReturn). The beauty of this design is that now you can simply right-click on any textField and assign the nextField outlet to the next SOTextField
object you want to be the next responder.
Moreover, you can do cool things like loop the textFields so that after the last one loses focus, the first one will receive focus again.
This can easily be extended to automatically assign the returnKeyType
of the SOTextField
to a UIReturnKeyNext
if there is a nextField assigned -- one less thing manually configure.
Here is my solution for this problem.
To solve this (and because I hate relying on tags to do stuff) I decided to add a custom property to the UITextField object. In other words I created a category on UITextField like this :
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
Now, here is how I use it :
UITextField *textField1 = ...init your textfield
UITextField *textField2 = ...init your textfield
UITextField *textField3 = ...init your textfield
textField1.nextTextField = textField2;
textField2.nextTextField = textField3;
textField3.nextTextField = nil;
And implement the textFieldShouldReturn method :
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
UITextField *next = theTextField.nextTextField;
if (next) {
[next becomeFirstResponder];
} else {
[theTextField resignFirstResponder];
}
return NO;
}
I now have kind of a linked list of UITextField, each one knowing who's next in the line.
Hope it'll help.
链接地址: http://www.djcxy.com/p/73498.html上一篇: 隐藏UITextField的游标
下一篇: 如何浏览文本框(下一个/完成按钮)