Instead of showing the keyboard I want to display a popover view when a textField is selected (my code is at the bottom). If the keyboard isn't showing then everything works great. However, if the keyboard is showing and then the textfield is selected the keyboard doesn't get dismissed, somewhere the firstResponders must be getting lost but I don't know where. Does anyone have a solution to this?
My textfield:
self.startDateTextField = [[UITextField alloc] initWithFrame:CGRectMake(79, 148, 138, 27)];
[self.startDateTextField setBorderStyle:UITextBorderStyleRoundedRect];
[self.startDateTextField setDelegate:delegate];
[self.startDateTextField addTarget:delegate action:#selector(editStartDate:) forControlEvents:UIControlEventEditingDidBegin];
[popoverWrapper addSubview:self.startDateTextField];
and in editStartDate: I have:
-(void)editStartDate:(UITextField *)textField {
[textField resignFirstResponder];
DatePickerVC *datePickerVC = [[DatePickerVC alloc] init];
datePickerVC.delegate = self;
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:datePickerVC];
[self.popoverController setDelegate:self];
[self.popoverController presentPopoverFromRect:CGRectMake(0, 0, 5, 5) inView:textField permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
}
This is very easy to do, use your UITextFieldDelegate methods specifically UITextFieldShouldBeginEditing and return NO and execute the code to show the popover instead. This way the keyboard is never shown to begin with.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
[self.view endEditing:YES]; // added this in for case when keyboard was already on screen
[self editStartDate:textField];
return NO;
}
for it to work make sure you set the delegate of the textField to self (the view controller) and in your editStartDate method remove the resignFirstResponder call.
Try like this in your editStartDate: method
[self.startDateTextField resignFirstResponder];
EDIT:
But instead of doing resign the keyboard when you click in textfield, you can make something like setInputView for Textfield to bring out the popViewController.
DatePickerVC *datePickerVC = [[DatePickerVC alloc] init];
datePickerVC.delegate = self;
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:datePickerVC];
[self.popoverController setDelegate:self];
[self.popoverController presentPopoverFromRect:CGRectMake(0, 0, 5, 5) inView:textField permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
self.startDateTextField = [[UITextField alloc] initWithFrame:CGRectMake(79, 148, 138, 27)];
[self.startDateTextField setBorderStyle:UITextBorderStyleRoundedRect];
[self.startDateTextField setDelegate:delegate];
self.startDateTextField.inputView = self.popoverController;
You appear to be resigning the first responder of the text field; however, this isn't necessarily the first responder, which may explain why calling it has no effect.
Instead, you should use the endEditing category to recurse through all children of your view to resign the first responder from whichever view it is attached to:
[self.view endEditing:YES];
In any case, as you never want to show the keyboard, you can simply implement UITextFieldDelegate to override the default behaviour.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
// Your popover code.
return NO;
}
UITextFieldDelegate Protocol Reference.
So you're trying to hide the keyboard immediately after the text field is selected and display something else?
There's two things I can think of:
Give the text field some time to get it together before resigning the first responder:
[textField performSelector:#selector(resignFirstResponder) withObject:nil afterDelay:0.5];
Set the inputView property of the text field to nil or a UIView with a clear background color.
If inputView on the text field doesn't get you what you want, you can also simply put an invisible button on top of the UITextField and just show the popover from the button's action. To the user it will appear as if the text field brought up the popover. If at that point the keyboard is still there, call resignFirstResponder on all possible first responders (text fields etc.).
Related
I have managed to add a UIPickerView as an input view to UITextField in viewDidLoad, but now I want to make the UITextField as first responder when another textfield (with tag =4) ends editing. This is the code I'm using:
This is in the viewdidload, and all the other code needed to initialize the picker view is there:
UIPickerView *myPickerView = [[UIPickerView alloc] init];
myPickerView.showsSelectionIndicator = YES;
myPickerView.delegate = self;
myPickerView.dataSource = self;
myPickerView.backgroundColor = [UIColor colorWithRed:76/255.0 green:76/255.0 blue:76/255.0 alpha:1];
textfieldInput.inputView = myPickerView;
This is in my text field did end editing method:
-(void)textFieldDidEndEditing:(UITextField *)textField{
if(textField.tag == 4){
[textfieldInput becomeFirstResponder];
}
The problem is that when the textfieldInput becomes the first responder, the picker view isn't shown, instead the keyboard is presented.
Also, it should be mentioned that i have another textfield on top of this that gets resigned if it became the first responder and becomes hidden. This textfield is the textfield that has a tag of 4. (This textfield has been added for design reasons).
This code works for me... are you sure that call the correct reference of textfield?
try: [self.textfield becomeFirstResponder];
I have designed a keyboard on my app Now I have the query is that whenever somebody tap on the textfield the keyboard on the device appear which i don't want
is there any way to disable the keyboard so that the user can see the keyboard designed on this app.
In your ViewController add the delegate of the UITextField :
#interface ViewController : UIViewController <UITextFieldDelegate>
While Creating the UITextField or in ViewDidLoad:
self.myTextField.delegate = self;
In your implementation file:
#pragma mark - UITextFieldDelegate
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[textField resignFirstResponder];
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
return NO;
}
Note that you can set the return of textFieldShouldBeginEditing to NO or YES according to your needs, in your case you may return YES , but provide the logic of displaying your custom keyboard
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
return NO;
}
And Needs to add delegate <UITextFieldDelegate>
In this method you also can write code to show your custom keyboard.
lol
Set the inputView to a zero sized view:
textField.inputView = [[UIView alloc] initWithFrame:CGRectZero];
You can use following approach to restrict keyboard display when user tap on it :
Method : 1
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
return NO;
}
This method hide the Keyboard and dont show the cursor.
Method : 2
UIView* HideView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)] autorelease];
textField.inputView = HideView;
This method hide the Keyboard, but Cursor is appear.
You can disable user interaction.
textField.userInteractionEnabled = NO;
I'd like to dismiss the keyboard with a text field using
- (BOOL)textFieldShouldReturn:(UITextField *)textField {, but I need to do the same with a text view, so I'll use - (BOOL)textViewShouldReturn:(UITextView *)textView {. Is it possible to put them togheter in the same AppDelegate?
Thank you.
Yes, you can have two delegates
#interface ViewController : UIViewController<UITextFieldDelegate,UITextViewDelegate>
Unfortunately
The protocol UITextViewDelegate does not have, something like this.
- (BOOL)textViewShouldReturn:(UITextView *)textView {
UITextViewDelegate Protocol,
EDIT 1 :
Button press event to hide the keyboard.
-(IBAction) yourButtonPressed:(id)sender;{
for(UIView *v in self.view.subviews){
if([v isKindOfClass:[UITextField class]] || [v isKindOfClass:[UITextView class]]){
if([v isFirstResponder]){
[v resignFirstResponder];
break;
}
}
}
}
I don't fully understand your question...
Basically you will do the following:
implement the UITextFieldDelegate and UITextViewDelegate in your
viewController
implement the methods of that delegates, you need/want
resignFirstResponder / endEditing of the textField / textView, where
ever you want
Just subscribe to the delegates from your viewController and make sure to set the delegate on those objects to your viewController.
.h
#interface YourViewController : UIViewController <UITextFieldDelegate, UITextViewDelegate>
.m
someTextField.delegate = self;
someTextView.delegate = self;
From the sound of it you just need to tie into the actions of the textField and textView. Create an IBAction and tie it to what you'd like. Then you can resignFirstResponder from that IBAction.
Use this action for both your textField and textView
- (IBAction)lowerTheText:(id)sender
{
[sender resignFirstResponder];
}
Yes, with a UITextView it's tricky. As I say in my book...
http://www.apeth.com/iOSBook/ch23.html#_uitextview
...on the iPad, the problem of dismissing the keyboard doesn't arise because the user can dismiss it with the button in the lower right corner of the keyboard. So this leaves only the iPhone. You will typically have an interface such that there is a Done button or similar. Look at how the Notes app solves this, for example.
The process itself is just the same: call endEditing: on the superview and whoever is first responder will cease being first responder and the keyboard will retire.
Yes, you can use textfield delegate and textview delegate in the same application.
TextField:
#interface ViewController : UIViewController<UITextFieldDelegate,UITextViewDelegate>
// This allocates the textfield and sets its frame (or) you can use interfaceBuild
UITextField *textField = [[UITextField alloc] initWithFrame:
CGRectMake(20, 50, 280, 30)];
textField.delegate=self;
// This method enables or disables the processing of return key
-(BOOL) textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder]; // this is event for hide keyboard.
return YES;
}
TextView:
// init
UITextView *textView = [[UITextView alloc] initWithFrame:
CGRectMake(20, 50, 280, 30)];
- (void)textViewDidChangeSelection:(UITextView *)textView
{
[textField resignFirstResponder]; // this is event for hide keyboard.
}
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).
I created a form and the keypad (Numeric only) appears when entering data like your age.
I want the keyboard to disappear when the user taps the background and I want to add a "Done" button in the empty slot under the 7 (next to the zero). (im using the Number Pad keyboard)
I found this example but I have a few questions.
In
-(void)viewDidLoad
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)]; [self.view addGestureRecognizer:tap];
}
-(void)dismissKeyboard
{
[aTextField resignFirstResponder];
[aTextField1 resignFirstResponder];
[aTextField2 resignFirstResponder];
[aTextField3 resignFirstResponder];
}
If I have more than 1 text field in my form.
Will I need to write every textfield in the dismissKeyboard method?
Easy way to do this is to use the method provided in UIView
- (BOOL) endEditing:(BOOL)force;
This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign.
So just do this:
-(void)dismissKeyboard {
[self.view endEditing:YES];
}
and it will support any more text fields you add on your page (under that UIView of course)
You should only send dismissKeyboard to that textField that you are currently editing.
In your code you have got memory leak. Better use this one:
-(void)viewDidLoad
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
[tap release];
}
To check if UITextField is currently in edit mode you can check its property:
A Boolean value indicating whether the text field is currently in edit mode. (read-only)
#property(nonatomic, readonly, getter=isEditing) BOOL editing
For example, you have 3 text fields then dismissKeyboard will look something like this:
-(void)dismissKeyboard
{
UITextField *activeTextField = nil;
if ([textField1 isEditing]) activeTextField = textField1;
else if ([textField2 isEditing]) activeTextField = textField2;
else if ([textField3 isEditing]) activeTextField = textField3;
if (activeTextField) [activeTextField resignFirstResponder];
}
I use the same functionality in many of my apps. Rather than using the GestureRecognizer, I set my view up as a UIControl, rather than a UIView. You can still do the things you'd do with a UIView, but you can also assign IBActions to be performed when interacting with the view.
Here's how to do it:
In Interface Builder, select your view. Then, assign its class to UIControl. (It's probably set up as UIView currently.
In your ViewController for that view, write an IBAction method to detect backgroundTaps. Mine looks like this:
- (IBAction)backgroundTap:(id)sender
{
if ([textField1 isEditing]) {
[textField1 resignFirstResponder];
} else if ([textField2 isEditing]) {
[textField2 resignFirstResponder];
}
}
Finally, in Interface Builder, connect the IBAction you created to the UIControl.
Read this article, it may help you
Writing iOS 4 Code to Hide the iPhone Keyboard (Xcode 4)
Here i give common text field object. and asign reference to it in "textFieldShouldBeginEditing" method. that will common for all text field..
In this case, you need to dismiss one text field that will hide keyboard..
declare textfield object in .h file.
#interface RootViewController : UIViewController
{
IBOutlet UITextField* txt_common;
}
IN .m file
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
[tap release];
}
-(void)dismissKeyboard
{
NSLog(#"hi");
[txt_common resignFirstResponder];
}
#pragma mark TextField methods
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
NSLog(#"hi++++++++++++++++++");
txt_common=textField;
return YES;
}