I have 3 custom objects which each contains 3 uitextfields.
when I press next in the keyboard I am able to pass focus to the next UITextFiled though textFieldShouldReturn and becomeFirstResponder. this is fine while they reside in the same parent view. But how can I pass focus to an UITextFiled in a different parent view?
Each row represents a different view. So my problem is passing focus from text3 to text4.
You'll want to use becomeFirstResponder on "text4". So, depending on how you have this all setup (I'll assume they're just IBOutlets) you'll want to do something along the lines of this:
- (IBAction) userHitReturnOnTextField:(UITextField *)sender {
if (sender == self.text1) [self.text2 becomeFirstResponder];
else if (sender == self.text2) [self.text3 becomeFirstResponder];
...
else [self.view endEditing:YES]; // hides the keyboard
}
Of course you can get more creative and store your UITextFields in an array and your logic will get simpler depending on the number of textfields you have:
- (IBAction) userHitReturnOnTextField:(UITextField *)sender {
int nextIndex = [self.myArrayOfTextFields indexOfObject:sender] + 1;
if (nextIndex < self.myArrayOfTextFields.count) {
UITextField *nextField = self.myArrayOfTextFields[nextIndex];
[nextField becomeFirstResponder];
} else [self.view endEditing:YES]; // hides the keyboard
}
Related
I'm trying to move my first responder on using tags in a tableview cell. I've set _txtFieldActive to pick up the active UITextFields tag. I can see this when I press the next button on the keyboard via NSLog. Now however I can't seem to figure out how to resignfirstresponder on that tag, and then move my first responder onto tag 102?? I get an error on the line of code trying to assign tag 102 to *tmp.
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
switch (textField.tag)
{
case 101:
//Do Nothing do not want to close keyboard but move on to next UITextField
if (_txtFieldActive.tag == 101)
{NSLog(#"Tag = 101");
UITextField *tmp = [textField.tag == 102];
[tmp becomeFirstResponder];
}
break;
case 102:
[textField resignFirstResponder];
}
return YES;
}
Many thanks all for your help in advance for any pointers.
Jon.
To get a reference to a view in the current view's hierarchy with a given tag, we need to call viewWithTag:.
if (_txtFieldActive.tag == 101) {
NSLog(#"Tag = 101");
UITextField *tmp = [self.view viewWithTag:102];
[tmp becomeFirstResponder];
}
Try that on for size.
If this is a UITableViewController subclass rather than a UIViewController subclass, you might need [self.tableView viewWithTag:102];, but self.view should work in either case.
Is it possible to dismiss the keyboard when you have MULTIPLE UITextFields ? If so how ?
As a side note, do I have to dismiss the keyboard for Each and Every field or can it be done globally ? Oh and it would be super cool if I don't have to touch the DONE button, I'd ideally like a solution that where the user touches anything BUT the field in question and the keyboard automagically disappears...
Oh and if you'd be so kind step by step instructions.
I should have added that I have a method already to resign the keyboard....
However, it only runs when my form is submitted! (see method below)
My question is how to the keyboard to hide/dismiss without having to jump thru so many damned hoops! You'd figure after 6 years, a mature operating system would have a way to GLOBALLY hide the keyboard....NOT!
Ok, enough whining....
- (void)hideKeyboard {
[self.dancePlace resignFirstResponder];
[self.danceGate resignFirstResponder];
[self.danceTerminal resignFirstResponder];
[self.danceText resignFirstResponder];
[self.danceDate resignFirstResponder];
[self.danceStyle resignFirstResponder];
[self.danceTimeOut resignFirstResponder];
}
And this is called when my button is submitted....
- (IBAction)addListingPressed:(id)sender {
// NSLog(#"BUTTON PRESSED");
[self hideKeyboard];
[self valuesAdded];
}
My question, assuming anyone can answer this...and I suspect not, is there a way to globally hide the keyboard if the following conditions are MET: 1.) the user taps OUT of any one of the existing fields, 2.) presses anywhere else on the screen. 3.) Is no more than a line or two in the existing viewcontroller.m file. 4.) I don't have to add a confusing button on the viewcontroller. (any time I have to add outlets, the damned thing is crashing on me...and then nastiness happens, and really...remember I am JUST a beginner, and its very confusing to read that I have to place this here and that there...oy. Simple folks, simple. I'm not looking for elegant solution, just so that it works.
I have a super class that all my view controllers inherit from. In that class I have this code.
MySuperViewController.h
#import <UIKit/UIKit.h>
#interface MySuperViewController : UIViewController
#property(strong, nonatomic) UITapGestureRecognizer *backgroundTapGestureRecognizer;
#end
MySuperViewController.m
- (void)viewDidLoad{
//add a tap gesture recognizer to capture all tap events
//this will include tap events when a user clicks off of a textfield
self.backgroundTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onBackgroundTap:)];
self.backgroundTapGestureRecognizer.numberOfTapsRequired = 1;
self.backgroundTapGestureRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:self.backgroundTapGestureRecognizer];
}
- (void)onBackgroundTap:(id)sender{
//when the tap gesture recognizer gets an event, it calls endEditing on the view controller's view
//this should dismiss the keyboard
[[self view] endEditing:YES];
}
I have the UITapGestureRecognizer as a public property, so I can override it if I need to.
subclass
MyViewController.h
#import <UIKit/UIKit.h>
#import "MySuperViewController.h"
#interface MyViewController : MySuperViewController<UIGestureRecognizerDelegate>
#end
MyViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//You don't always want the keyboard to be dismissed, so you tie into the gesture recognizer's delegate method
//By doing this, you can stop the endEditing call from being made
[self.backgroundTapGestureRecognizer setDelegate:self];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
//touch.view is the view that recieved the touch
//if this view is another textfield or maybe a button, you can return NO and the endEditing call won't be made
if (touch.view == self.myViewThatShouldNotBeBlocked) {
return NO;
}
//if you want the gesture recognizer to accept the event, return yest
return YES;
}
I uploaded an example project to github.
https://github.com/JeffRegan/KeyboardBeGone
RDVKeyboardAvoiding is a scroll view with a tap gesture recognizer, designed for multiple textViews/textFields. It keeps track of the active view and removes a lot of boilerplate code.
tap anywhere outside the textField .. it will hide it..
[self.view endEditing:YES];
There are couple of other ways to do it.
[myEditField resignFirstResponder];
[myEditField endEditing];
[parentView endEditing];
If you dont wont to do so many things and simply want to dismiss keyboard than give iboutlet to each of your text filed to following method..
-(IBAction)hidekeyboard:(id)sender
{
[sender resignFirstResponder];
}
Yes, you only have to dismiss it for the one that is currently being edited.
In order to know which one is being edited, you can check the -(BOOL)isFirstResponder property, which will return YES if it is the first responder (the one being edited) or NO if it is not. Once you know which one is the first responder you can call -(void)resignFirstResponder on that one to get rid of the keyboard.
For example, if you have a method called -(void)aMethod that you want to dismiss the current view controller and you have an array of textViews called textArray, you could do a little loop such as:
-(void)aMethod {
for (UITextField *text in self.textArray) {
if ([text isFirstResponder]) [text resignFirstResponder];
return;
}
}
This way, you can have a variable number of textFields and it will still work.
If you only have one or two textFields and you do not want to create an Array object, you could do (assuming the fields are named text1 and text2:
-(void)aMethod {
if ([text1 isFirstResponder]) [text1 resignFirstResponder];
else if([text2 isFirstResponder]) [text2 resignFirstResponder];
}
Also, to make things easier for the future you could create a category method for UIView (which is what I do) to get the current first responder if it exists as a subview of that view:
#implementation UIView (GetFirstResponder)
- (UIView *)getFirstResponder {
if ([self isFirstResponder]) return self;
else {
for (UIView *subview in self.subviews) {
UIView *firstResponder = [subview getFirstResponder];
if (firstResponder) return firstResponder;
}
}
return nil;
}
You can put this method on the top of any file that you want to call it from, or create a separate file for it and import it.
Once you have this method, you can call:
- (void)aMethod {
UIView *view = [self.view getFirstResponder];
if (view) [view resignFirstResponder];
}
[superview endEditing:YES]; // superview can be the view controller's view property.
iOS6
I have 6 UITextFields in a Scene with a Next Button that Segue's into the next Scene.
The code below works great when I hit the Done button on the keyboard:
- (IBAction)dismissKeyboard:(id)sender
{
if (sender == LocationName) {
self.meeting.LocationName = LocationName.text;
}
if (sender == LocationAddress) {
self.meeting.LocationAddress = LocationAddress.text;
}
if (sender == LocationCity) {
self.meeting.LocationCity = LocationCity.text;
}
//I have 3 more text fields after and then I persist to CoreData:
NSError *error = nil;
if (![managedObjectContext save:&error]) {
}
[sender endEditing:YES];
}
If the user hits the Done Button on the Keyboard, the data saves fine.
However, if the User hits the Next Button on the Navigation Bar, without hitting the Done button on the keyboard first, the user Typed inside the UITextfield DOES NOT SAVE. I would like for the user typed Data (Data that user inputted from the keyboard) in all the fields to be saved when the user hits the Next Button on the Navigation Bar to call the next scene.
I have the following code for the Next Button:
- (IBAction)nextButtonPressed:(id)sender {
[self dismissKeyboard:sender];
}
I know the code for nextButtonPressed is wrong. I think I need help with identifying which UITextField called the Keyboard to be visible, and then call the dismissKeyboard with passing the Sender as a parameter.
Thanks
Make use of the UITextField delegate method textFieldDidEndEditing: to know when the focus leaves a text field. This is when you should save its data. This will be called when focus moves to another text field or when the keyboard is completely dismissed.
Your implementation of nextButtonPressed: should simply call becomeFirstResponder on whatever the next text field is. That's it. By making another text field the first responder, the previous one will have its textFieldDidEndEditing: delegate called.
Update:
// This assumes the LocationXXX are instance variables referencing the UITextFields
- (IBAction)nextButtonPressed:(id)sender {
if (sender == LocationName) {
[LocationAddress becomeFirstResponder];
} else if (sender == LocationAddress) {
[LocationCity becomeFirstResponder];
// add the rest as needed
}
}
In my app I have a view that is a form that has quite a few inputs.
When the UITextField calls textFieldDidBeginEditing, it checks the tag and will bring up a UIPopoverController or the keyboard depending on the what the input is meant to be.
If the keyboard is up, I need it disappear when the user presses a textfield that brings up the popover. However I cannot make it disappear, I have tried every way to get rid of the keyboard but it just stays there. I have tried:
calling resignFirstResponder in textFieldDidEndEditing
calling [self.view endEditing:YES] in textFieldDidEndEditing
calling resignFirstResponder AND [self.view endEditing:YES] in textFieldDidBeginEditing checking for the previous tag is equal to a keyboard input text field.
Any ideas would be great.
I have ripped it out and and put it in a example project if anyone wants to see the exact behaviour.
http://dl.dropbox.com/u/61692457/KB_Test.zip
Declare a Global UITextField in .h file
UITextField *txtfld;
Replace Your method textFieldDidBeginEditing with textFieldShouldBeginEditing and now write this code
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if (textField.tag == 1 || textField.tag==3)
{
if(numPickerPopover == nil)
{
numPicker = [[[NumPicker alloc] initWithStyle:UITableViewStylePlain] autorelease];
numPicker.delegate = self;
numPickerPopover = [[UIPopoverController alloc] initWithContentViewController:numPicker];
[numPickerPopover setPopoverContentSize:CGSizeMake(60.0, 260.0f)];
}
[numPickerPopover presentPopoverFromRect:textField.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[txtfld resignFirstResponder];
return NO;
}
if (textField.tag == 2)
{
txtfld = textField;
return YES;
}
return YES;
}
To dismiss the keyboard when the user touches the textField that brought it up, add this method:
- (IBAction)dismissKeyboard:(id)sender {
[textField resignFirstResponder];
}
In Interface Builder, connect this method to the textField event you want, like touch up inside (or whatever is more appropriate).
now i have a textField.
and i enter some words,the keyboard will appear.
when i pressed the keyboard "done",the keyboard will disappear. (i have finished this function)
but next,
i want to insert data using core data framework when the user pressed the button "done"
so,how to solve this problem?
i know how to insert data using core data,so you do not need to tell me how to insert the data.
i am using this code to disappear keyboard.
-(BOOL)textFieldShouldReturn:(UITextField *)theTextField {
[txtName resignFirstResponder];
return YES;
}
thanks everybody
In the example code, I have 3 UITextField. You can process your update after we reach the last field
// I the tag property to indicate which field I am on during runtime
enum {
Line1Tag = 50,
Line2Tag,
Line3Tag
};
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
// The user has pressed the "Return Key"
// Which I have set to "Next" for first two lines
// and "Done" for the last line, so jump to the next text field
NSLog(#"\"Return\" key pressed.");
// based on which text field we are in jump to the next
if (textField.tag == Line3Tag)
// We have reach the last line so hide keyboard
[textField resignFirstResponder];
// this is where you can perform Core Data updates if you like
else {
int nextTag = textField.tag + 1;
UIView *nextField = [self.view viewWithTag:nextTag];
[nextField becomeFirstResponder];
// Once the next text field is the first responder
// I need to make sure the user can see it
[self makeActiveTextFieldVisible];
}
return NO;
}