In my code I have:
-(BOOL)textFieldShouldReturn:(UITextField*)theTextField{
if (theTextField == ITload)
{
[ITload resignFirstResponder];
return YES;
}
if (theTextField == FacilitiesLoad) {
[FacilitiesLoad resignFirstResponder];
return YES;
}
return NO;
}
ITload and FacilitiesLoad are both my text fields. I'm using Numerical with punctuation keyboard and no done key appears. I have a return key which doesnt close the keyboard down.
Any ideas on how to display a done key and to get textFieldShouldReturn working please?
It seems that you haven't set the delegate of your text fields to your receiver.
ITLoad.delegate = self;
FacilitiesLoad.delegate = self;
EDIT: you're getting warnings because your view controller doesn't (formally) comforms to the UITextFieldDelegate protocol. Declare it like this:
#interface MyViewController: UIViewController <UITextFieldDelegate> {
}
etc.
Related
I wrote a textFieldDone: method that's suppose to move the cursor to the next textfield when the Return button is tapped.
- (IBAction)textFieldDone:(id)sender {
[nextTextField becomeFirstResponder];
NSLog(#"in : textFieldDone");
}
I have connected the first textfield's "Did End On Exit" event to the File's Owner and chose the textFieldDone: method.
I also assigned the File's Owner as the textfield's delegate (because I need the view to scroll up/down accordingly so the keyboard won't hide the textfields).
When I run the app on the simulator and tap the return button the first textfield resign first responder and in the log I see that the program didn't go through the textFieldDone: method, but it did go through the textFieldDidEndEditing: method.
I used that method before and had no problem.
Is it because the File's Owner is the textfield's delegate?
You need to write on
- (BOOL) textFieldShouldReturn:(UITextField*) textField
to go to next text field.
Sample code:
-(BOOL) textFieldShouldReturn:(UITextField*) textField
{
if (textField == txt1)
{
[txt1 resignFirstResponder];
[txt2 becomeFirstResponder];
}
if (textField == txt2)
{
[txt2 resignFirstResponder];
}
return YES;
}
Don't forget to add delegate UITextFieldDelegate to your UITextfield.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if ([textField isEqual:txt1])
{
[txt2 becomeFirstResponder];
}
return true;
}
the above answers are correct, but to make this more general you should use the tag option
UITextField *txt1;
txt1.tag=1;
UITextField *txt2;
txt2.tag=2;
UITextField *txt3;
txt3.tag=3;
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if ([[textField superview] viewWithTag:textField.tag+1])
{
[[[textField superview] viewWithTag:textField.tag+1] becomeFirstResponder];
}
else{ [textField resignFirstResponder];
}
return true;
}
note: don't use textField with tag 0. because all subViews have tag=0 by default.
So i was reading the description about UITextView's and it says that it automatically hides the keyboard when you press the 'Return' button on the keyboard. But it wasn't working, so I tried creating an
- (IBAction)textViewReturn:(id)sender;
{
[myTextView resignFirstResponder];
}
That did not work either so i tried also doing:
- (BOOL)textViewShouldReturn:(UITextView *)textView
{
[myTextView resignFirstResponder];
return NO;
}
Not sure why the whole deal isn't working in the first place. Wondering if anyone could help?
I don't see anything in the UITextView Class Reference that says it automatically hides the keyboard when you press Return.
Also, there is no textViewShouldReturn: message in the UITextViewDelegate protocol. There is a textFieldShouldReturn: message in the UITextFieldDelegate protocol, but a text view is not a text field.
If you want it to hide the keyboard when the user presses Return, you need to do two things.
First, you need to connect some object - usually your view controller - to the text view's delegate outlet. You can do that in your nib, or you can do it in code, perhaps in your viewDidLoad method:
- (void)viewDidLoad {
[super viewDidLoad];
myTextView.delegate = self;
}
Second, you need to implement the textView:shouldChangeTextInRange:replacementText: in your delegate object:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if ([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
} else {
return YES;
}
}
Note that if the user pastes in text containing a newline and other characters, this will not catch the newline. It will only notice when the user either taps the Return key, or when he pastes in text containing just a newline.
You can declare the delegate's class as conforming to the UITextViewDelegate protocol, in which case Xcode will helpfully autocomplete the method name. But it will work even if the class doesn't conform to the protocol.
Return button of UITextView is used to mote the cursor to the new line. But if you want to remove the keyboard on return button then please try the following code. It resigns the keyboard when return button is pressed by user. So try following code which definitely solved your problem.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if ([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
} else {
return YES;
}
}
Per your comment, if you want to use a UITextField instead of a UITextView, then things remain the same except that in order to hide the keyboard when you hit return, you need to implement the following function in the text field's delegate (make sure that you have set this first):
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
I'm making a login screen for my app and i want the return button to say "Next" when there is a field that is not yet filled out and it sould say "Go" when all fields are filled (i'm talking about UITextFields).
The code below works fine in that it shows Next and Go at the correct moments. But whenever it changes from "Next" to "Go" the next tap on the keyboard is ignored. When it says "Go" and i empty the textfield by backspacing there is no such problem and it shows Next as it should. It's almost like the old keyboard is still there and vanishes after being tapped.
My question is: what is the source of this problem and more importantly how do i get rid of this freezing up of the keyboard?
UITextField *theSender = (UITextField *)sender;
if (allTextFieldsAreFilled) {
if (theSender.returnKeyType!=UIReturnKeyGo) {
theSender.returnKeyType = UIReturnKeyGo;
[theSender resignFirstResponder];
[theSender becomeFirstResponder];
}
} else {
if (theSender.returnKeyType!=UIReturnKeyNext) {
theSender.returnKeyType = UIReturnKeyNext;
[theSender resignFirstResponder];
[theSender becomeFirstResponder];
}
}
This code gets called every time the value of one of the three UITextFields is changed, so it is an IBAction connected to the Editing Changed event.
Thanks in advance for your help!
EDIT
I found out this will only occur if the textfield is set to secure (password). When it is not set to secure it will not freeze up and my code works perfectly! The problem is that the change to the "Go" button will generally occur when a 'secure' textfield is fist responder. So this doesn't change anything to the problem.
I created a new Single View Application project to test this out; and dropped the following code in the ViewController.m
#import "ViewController.h"
#interface ViewController () <UITextFieldDelegate>
{
#private
IBOutlet UITextField* m_fieldA;
IBOutlet UITextField* m_fieldB;
IBOutlet UITextField* m_fieldC;
}
#end
#implementation ViewController
// connected to Editing Did Begin
- (IBAction) onFocus:(UITextField*)_textField
{
[self updateKeyboardFor:_textField];
}
// connected to Editing Changed
- (IBAction) onChanged:(UITextField*)_textField
{
[self updateKeyboardFor:_textField];
}
- (void) updateKeyboardFor:(UITextField*)_textField
{
bool allTextFieldsAreFilled = [m_fieldA.text length] && [m_fieldB.text length] && [m_fieldC.text length];
if (allTextFieldsAreFilled)
{
if (_textField.returnKeyType != UIReturnKeyGo)
{
_textField.returnKeyType = UIReturnKeyGo;
//[_textField resignFirstResponder];
//[_textField becomeFirstResponder];
[_textField reloadInputViews];
}
}
else
{
if (_textField.returnKeyType != UIReturnKeyNext)
{
_textField.returnKeyType = UIReturnKeyNext;
//[_textField resignFirstResponder];
//[_textField becomeFirstResponder];
[_textField reloadInputViews];
}
}
}
// A part of UITextFieldDelegate
- (BOOL) textFieldShouldReturn:(UITextField*)_textField
{
if (_textField.returnKeyType == UIReturnKeyGo)
{
[_textField resignFirstResponder];
// go off and perform 'go'
}
else
{
if(_textField == m_fieldA) [m_fieldB becomeFirstResponder];
if(_textField == m_fieldB) [m_fieldC becomeFirstResponder];
if(_textField == m_fieldC) [m_fieldA becomeFirstResponder];
}
return true;
}
#end
Then in the XIB create three UITextFields and hooked them up to the IBOutlets, IBActions, and also set this view controller as the delegate for all the fields.
All seems to work fine regardless of secure fields.
My guess is that your issue is somewhere in the code where you move to the 'Next' field; and not in the code that you posted. Also make sure that all your outlets and delegates are linked up properly.
Update: I've edited the code above. The commented out lines were the problem, you should be using reloadInputViews to update the button.
It seems that it wasn't locking the keyboard; but what it was doing was after you typed the first letter and did the resign/become calls to refresh the button then the second press would overwrite the first. This seems like a bug in iOS... it's more noticeable if after the first letter you type a space. When I noticed that I added a label that updated it's content with the contents of the password field and it was even more clear what was happening.
I have an iPad application which has a sign up form within it. The form is very basic and contains only two UITextFields which are for Name & Email address.
The first TextField is for the candidates Name, When they enter their name in and press 'Next' on the keyboard I want this to automatically move to the next Email Address TextField to editing.
Any idea how I can set the next button the keyboard to jump to the next keyboard?
Thanks
You need to make your view controller the UITextField delegate, and implement the UITextField delegate method:
- (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 version:
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
}
You may also want to scroll your view for the emailField to become visible. If your view controller is an instance of UITableViewController, this should happen automatically. If not, you should read this Apple document, especially Moving Content That Is Located Under the Keyboard part.
Additionally to #lawicko 's answer I often change the button text to give that final finishing touch (e.g. says next when there are more fields and then done when on the last):
- (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 version of correct answer.
In my experience, you do not need to resignFirstResponder when switching textFields.
In this example, it's just your basic username and password textFields.
The keyboard "return key" in storyboard for username is set to "Next" and the one for password is set to "Done".
Then just connect the delegates for these two text fields and add this extension and you're pretty much done.
extension LoginViewController: UITextFieldDelegate {
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField == textFieldPassword {
self.view.endEditing(true)
} else {
textFieldPassword.becomeFirstResponder()
}
return true
}
}
A more consistent and robust way is to use NextResponderTextField
You can configure it totally from interface builder.
All you need to do is
Set the class type of your UITextField to be NextResponderTextField
Then set the outlet of the nextResponderField to point to the next responder it can be anything UITextField or any UIResponder subclass. It can be also a UIButton and the library is smart enough to trigger the TouchUpInside event of the button only if it's enabled.
Here is the library in action:
A Swift 4 extension. Just pass the array of UITextFields and it will connect each one to the next until the last one which resigns the first responder (hides the keyboard):
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)
}
}
- (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;
Make an outlet for the textfield, then
viewController.h
(IBAction)textFieldDoneEditing:(id)sender;
viewController.m
(IBAction)textFieldDoneEditing:(id)sender {
[textField resignFirstResponder];
if (textField == nameField) {
[emailField becomeFirstResponder];
}
}
Make the relation between (show the connections inspector > Sent Events)didEndOnExit and textFieldDoneEditing
I have two textfield, in first textfield I write "Hello" and when I push enter in iPad keyboard, I want that in second textfield appear "World"; How can I use enter to create an action in my application?
You would typically assign your view controller as the text field's delegate and then implement the textFieldShouldReturn: method, e.g.:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
otherTextField.text = #"World"
return YES;
}
You can do that by implementing the UITextFieldDelegate protocol in your controller. For instance you could do something like:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == theFirstTextField && [textField.text isEqualToString:#"Hello"]) {
theSecondTextField.text = #"World";
}
return YES;
}
Set your view controller to be the textfield's delegate then implement
-(BOOL)textFieldShouldReturn:(UITextField *)textField
this gets called when the enter button is pushed on the keyboard.
This is roughly what you'd do. Tweaking to condition around device-type (if you truly want iPad only):
#pragma mark - UITextField Delegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.firstTextField && [textField.text isEqualToString:#"Hello"]) {
self.secondTextField.text = #"World";
}
return YES;
}