Why resignFirst Responder does not hide keyboard? - ios

This is my custom UITextField class:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.delegate = self;
[self addTarget:self action:#selector(hideKeyboard) forControlEvents:UIControlEventTouchUpOutside];
}
return self;
}
- (void) hideKeyboard
{
NSLog(#"Clicked outside");
[self resignFirstResponder];
}
However, when I click outside of the text field, hideKeyboard never gets called. Can anyone explain why and how should I fix this?

The event you registered for will only happen if you begin the touch inside the text field and finish the touch outside of the text field.
If you start the touch outside the text field, the text field does not get any event.
Add a touch gesture recognizer to the view that contains the text field. When that event is triggered, resign the current first responder.

Your touches could be swallowed by some other UIControl that is consuming them. Without seeing your hierarchy it's impossible to tell.
However, I wouldn't suggest this even if you just had 1 UITextField on a blank UIView; it doesn't scale well, and could lead to strange bugs later if you add another UIControl to the view. What happens if you have this TextField and a UIButton in the same UIView?
Rather, I'd change the superview to be a UIControl (subclass of UIView), and just use UIControlEventTouchUpInside to trigger a method that dismisses the keyboard.

Related

resignFirstResponder programmatically [duplicate]

This question already has answers here:
Understanding resignFirstResponder with UITextField
(3 answers)
Closed 9 years ago.
How do I remove a keyboard from the view as a result of the return key being touched when the UITextField was created programmatically.
If the UITextField was called in the viewDidLoad I know how to do this, but the UITextField was created as a result of an -(IBAction).
I created my UITextField programmatically. I know the resignFirstResponder removes the keyboard. I have it set up to do so when the screen is taped outsie the keyboard. I also have it working to where if the user triggers the IBAction with the UIButton related to the UITextField the keyboard goes away. I also want to be able to hide the keyboard when the user selects return from the keyboard.
You need to make yourself a UITextFieldDelegate and implement:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
Make sure you set the textField's delegate to self when you create it.
You can use this:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return NO;
}
You'll need to set your text field's delegate to self first, though:
self.textField.delegate = self;
Or, you could right-click-drag from the text field in IB to little orange circle at the bottom.

How to make to keyboard has behavior like in default apps when text field is inside scroll view?

I have created in storyboard simple app (only one controller), I put scrollview and inside scrollview couple UITextFileds. Inside controller I have added function like
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.name resignFirstResponder];
[self.number resignFirstResponder];
// I have tried with and without this line but doesn't work
[self.scrollView resignFirstResponder];
}
(name, number are Outlets of UITextField, scrollView is Outlet of UIScrollView). When I click on any of those text fields keyboard pops up but when I finish typing I cannot hide keyboard.
(In previous version I didn't have scrollview and keyboard hides when I click out the text field). How to make to keyboard has behavior like in default apps, how to hide ?
I'm assuming you want to just be able to tap away from the keyboard and have it dismissed right? Just do this:
UITapGestureRecognizer *myTapz = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(userTapped)];
myTapz.numberOfTapsRequired=1;
myTapz.cancelsTouchesInView=NO;
[self.view addGestureRecognizer:myTapz];//or do self.WhateverYourOtherViewIsCalled..tableview? scrollView?
[myTapz release];
And then in your selector:
-(IBAction)userTapped
{
[whateverYourTextFieldIsCalled resignFirstResponder];
}
In your view controller:
[self.view endEditing:YES];
This will dismiss the keyboard no matter what field is the first responder. I think there are some exceptions, but for what you're doing it should work fine.
Also touchesBegan is a UIView method, not a UIViewController method. If you're putting it inside your UIScrollView, the scroll view's panGestureRecognizer is going to prevent touchesBegan from being called. Also when overriding touchesBegan, or other touches methods, you typically want to call super as well.
ttarules's suggestion for creating a gesture recognizer is the best way for detecting touches. You can use touchesBegan inside the view, just know that other gesture recognizers can prevent it from being called (see Session 121 - Advanced Gesture Recognition from WWDC 2010).
endEditing is the best way to dismiss the keyboard because it works even after you add other fields.

Detect tap on UIView's "empty space"

I've got a view hierarchy that looks like that
UIScrollView
|
+- UIView
|
+- UITextField
+- UITextField
+- UIButton
What I want is for user which tapped one of the text fields and sees the keyboard on the screen to be able to tap on an "empty space" of UIView to hide keyboard. So, I don't want, for instance, an event from UIButton to bubble up to UIView (that's exactly what happens if I add UITapGestureRecognizer to UIView).
How can I achieve the desired functionality?
In your viewDidLoad method add this gesture recognizer:
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
gestureRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:gestureRecognizer];
Then add the dismissKeyboard method:
- (void) dismissKeyboard{
[YOURFIELDHERE resignFirstResponder];
}
You also need to add this to make it so the buttons are still clickable and not overridden by the gesture recognizer:
gestureRecognizer.delegate = self; // in viewDidLoad
<UIGestureRecognizerDelegate> //in your header file
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIButton class]]){
return NO;
}
return YES; // handle the touch
}
I encounter this same problem and solve it with a naive solution.
Change the View from an instance of UIView to an instance of UIControl so that it can handle touch events.
Create an IBAction method in the View Controller that handles the touch event. In this case, we will resign any first responder from the view's subviews.
- (IBAction)backgroundTapped:(id)sender
{
[contentView endEditing:YES];
}
contentView is just the instance variable pointing to the View. You can name it anything you want. When you passed the message endEditing to the View, it essentially tells its subviews to resign first responder, thus dismissing the keyboard.
Connect the target (View) and action (IBAction method you just created) via Interface Builder, by opening the connection inspector of the View, select Touch Up Inside and drag it to the File's Owner object, then select the name of the method.
Hopefully it helps.
I know it's a little late, but a quick, simple solution is the following:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];
}
It gets called if you tap on any empty space.
Mike Z's answer is good. But I think the "if condition" below would be easier and simple in UIGestureRecognizerDelegate when you use Mike Z's answer.
Especially when the subviews are not only a button type, they may also be UITableViewCell, Custom View, etc.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return touch.view == yourEmptySpaceView;
}

Adding [myUITextField becomeFirstResponder]; does not bring up keyboard

I've created a screen that has a UITextField on it. When I get a EditingDidBegin event, I resignFirstResponder, Bring up a Popover with another textField in it and for that TextField call the BecomeFirstResponder on it.
When it runs, I get Blinking insertion pointer and the X clear contents. Though no Keyboard. The Master UIView is set to UserInteractionEnabled:YES.
target action for First UITextField, its on its own view.
[textField addTarget:self action:#selector(wantsToEditValue:) forControlEvents:UIControlEventEditingDidBegin];
Target Action selector:
- (IBAction)wantsToEditValue:(id)sender {
// set notification so we can update from popover
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(saWriteValue:)
name:kRefreshFromPopover object:nil];
//we dont want the TagValue textfield to really be the first responder.
[textField resignFirstResponder];
[... setup popoverVC, and View. present popover...]
}
Here is the code to create the 2nd UITextField. This code is in the VC for the Popover..
- (void)viewDidLoad
{
if (IoUIDebug & IoUIDebugSelectorNames) {
NSLog(#"%# - %#", [self description], NSStringFromSelector(_cmd) );
} [super viewDidLoad];
[self createElementInputControl];
[self createWriteButton];
//We want the input Focus
[textFieldInput becomeFirstResponder];
//Resize our view to handle the new width
CGRect newViewSize = CGRectMake(self.view.frame.origin.x,
self.view.frame.origin.y,
writeButton.frame.origin.x + writeButton.frame.size.width + kWriteElementOffset ,
self.view.frame.size.height);
[self.view setFrame:newViewSize];
}
Create Input Code:
-(void) createElementInputControl {
textFieldInput = [[UITextField alloc] initWithFrame:CGRectMake( kWriteElementOffset ,
kWriteElementHeightOffset,
kTagValueInputInitialWidth,
kWriteElementDefaultHeight)];
textFieldInput.borderStyle = UITextBorderStyleRoundedRect;
textFieldInput.clearButtonMode = UITextFieldViewModeWhileEditing;
textFieldInput.textAlignment = UITextAlignmentLeft;
[textFieldInput setDelegate:self];
[textFieldInput setKeyboardType:UIKeyboardTypeDefault];
// Set the value of the text
[textFieldInput setText:self.myTag.value];
CGSize textFieldInputSize = [textFieldInput.text sizeWithFont:textFieldInput.font];
//Set the Button Width
[textFieldInput setFrame:CGRectMake(textFieldInput.frame.origin.x, textFieldInput.frame.origin.y, textFieldInputSize.width + kTagValueInputWidthBuffer, textFieldInput.frame.size.height)];
[self.view addSubview:textFieldInput];
}
When I remove the becomeFirstResponder code, the Popover come up as normal, though no blinking insertion pointer. I tap the field, I get Insertion Pointer, X clear content button, and yes a Keyboard.
I want the keyboard to show without having to click in the new Text Field.
Thanks!
In order to become a first responder, the view must be in the view hierarchy.
You need to add your textFieldInput as a subview to something.
As per Apple's doc in UIResponder:
You may call this method to make a responder object such as a view the first responder. However, you should only call it on that view if it is part of a view hierarchy. If the view’s window property holds a UIWindow object, it has been installed in a view hierarchy; if it returns nil, the view is detached from any hierarchy.
When you call the become first responder from the didBeginEditing you will run into an infinite loop.Reason being, when you call becomeFirstResponder it calls didBeginEditing. So It Explains the cursor blink and your statement
When I remove the becomeFirstResponder code, the Popover come up as
normal, though no blinking insertion pointer. I tap the field, I get
Insertion Pointer, X clear content button, and yes a Keyboard.
To solve your problem,
In the beginEditingMethod ,
if(texfield.tag == firstTextFieldTag)
{
//Create second TextField and make it become first responder
}
else
{
// do want you want in the beginEditing of your second textfield.
}

Force keyboard to show up via button (iOS)

I have an UITextView and I don't want check editable option, how can call keyboard via a button?
This code doesn't work for me!
-(IBAction) yourButtonClick
{
[myTextView becomeFirstResponder];
[self.view addSubview:myTextView];
}
From the iPhone Application Programming Guide
However, you can programmatically
display the keyboard for an editable
text view by calling that view’s
becomeFirstResponder method. Calling
this method makes the target view the
first responder and begins the editing
process just as if the user had tapped
on the view.
So to show the keyboard programmatically,
[textView becomeFirstResponder];
However, the keyboard will never show if the textView is not editable.
The purpose of showing the keyboard is to allow editing. I assume you just don't want the keyboard to appear when the user taps the text view. In this case, you can enable editable programmatically when the button is tapped.
-(IBAction) yourButtonClick
{
myText.editable = YES;
[myText becomeFirstResponder];
}
Then in the UITextViewDelegate, disable editable when the user finishes editing.
- (void)textViewDidEndEditing:(UITextView *)textView {
textView.editable = NO;
}

Resources