I'm using MMDrawerController as a side menu. I can't find where to close the keyboard in center view when I open the side menu.
I've tried
write [self.view endEditing:YES] in sideMenuViewController's viewWillAppear method.
addObserver in centerViewController which called [self.view endEditing:YES] and postObserver in sideMenuViewController's viewWillAppear method.
It just don't work and cause like this...
Anyone has an idea to fix it?
today I met the same problem :)
I have spend several hours debugging the MMDrawer library and I have found solution of some kind. My solutions contains of two steps:
1) In MMDrawerController.m file - in the implementation of method: -(void)toggleDrawerSide:(MMDrawerSide)drawerSide animated:(BOOL)animated completion:(void (^)(BOOL finished))completion add at the beginning of the method, the following code: [self.centerViewController.view endEditing:true];. With this code you close the keyboard when tapping on menu burger - all views that are subviews for the current centerViewController try to resignFirstResponder.
2) In MMDrawerController.m file - in the implementation of method: -(void)panGestureCallback:(UIPanGestureRecognizer *)panGesture replace the else statement of case UIGestureRecognizerStateBegan with the following code:
else {
//hide keyboard when pan gesture start
[self.centerViewController.view endEditing:true];
self.startingPanRect = self.centerContainerView.frame;
}
And I am giving you the old code - coming from the library just for more detail explanation:
else {
self.startingPanRect = self.centerContainerView.frame;
}
With this code you close the keyboard when starting pan gesture, if such pan gesture is allowed for side menu - all views that are subviews for the current centerViewController try to resignFirstResponder.
P.S. I have tried to put this code in another method, but it behave a little strange because of the animation completion block after the movement of the centerViewController is done. So I think endEditing: in the beginning of the pan gesture is the way to go.
Hope that could help you!
I found the solution
In your CentralView controller
#pragma mark - Button Handlers
-(void)leftDrawerButtonPress:(id)sender{
[self.mm_drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];
[self.textfield resignFirstResponder];
}
Try this method. It is working for me
You don't have a use observer for this, just have IBOutlet property for your UITextField say "textfield".
[self.textfield resignFirstResponder];
add this line when you sideMenuViewController's viewWillAppear.
For anyone who still has problems with opening the drawer using a gesture, use the following code:
Put the code where you initialize your drawer controllers.
[self.drawerController setGestureCompletionBlock:^(MMDrawerController *drawerController, UIGestureRecognizer *gesture) {
// hide the keyboard when the gesture completes
if(drawerController.openSide == MMDrawerSideLeft) {
[[UIApplication sharedApplication] sendAction:#selector(resignFirstResponder) to:nil from:nil forEvent:nil];
}
}];
Related
I cant seem to find this answer for the manually clearing the UISearchBar with a backspace, only with a cancel button click. The code below hides the keyboard when the clear button is clicked, but so does the backspace to an empty UISearchBar. Id like to leave the keyboard open in that scenario since someone might be typing something else.
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
{
[self filterData: text];
if(text.length == 0)
{
[searchBar performSelector:#selector(resignFirstResponder) withObject:nil afterDelay:.1];
}
}
Your code includes if(text.length == 0) and that means that when the size of the input becomes zero, keyboard is dismissed. However the actual piece should be as follows:
- (BOOL) searchBarCancelButtonClicked:(UISearchBar *)searchBar{
[searchBar resignFirstResponder];
return YES;
}
My best try on such an issue is to do as suggested here BUT IT DOES NOT WORK WHEN YOU CLICK CLEAR BUTTON :( but I thought it might help you though:
https://stackoverflow.com/a/16957073/1465756
Add a tap gesture on your whole view:
- (void)viewDidLoad
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
}
and dismissKeyboard when the view is tapped:
- (void) dismissKeyboard
{
[self.searchBar resignFirstResponder];
}
I understand you want to dismiss the keyboard when the user hits Cancel, and you also want to dismiss when the user hits the clear (x) button.
You do not need to implement searchBar:textDidChange:.
To detect cancellation, implement searchBarCancelButtonClicked:. Here you can trigger resignFirstResponder.
To detect clear, adopt UITextFieldDelegate and implement textFieldShouldClear:. This will be called after the user taps clear, but before the clear occurs. Return YES to allow the clear to occur. You may dismiss the keyboard before returning.
I'm writing an app in which I want to dismiss the keyboard by clicking in the background. I know I need to type in the following code somewhere after dragging one of the "Sent Events" dots to somewhere on the view controller. Assume for this example that the text field is called textField.
-(IBAction)backgroundTap:(id)sender {
[textField resignFirstResponder];
}
Which dot do I need to drag from in "Sent Events" and to where? I know that this is the code that will work, but I can never remember which dot to use and where to drop it on the screen.
Thank you!
Usually when I need to resign first responder in the event of a background tap, I overwrite the - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event UIViewController method, and in there, I resign first responders. I'm not sure if this is possible using Interface Builder in one quick action.
Use button in background to click out..and write simple code for click EVENT TOUCH UP INSIDE
-(IBAction)backgroundbuttonpress:(id)sender
{
[textField resignFirstResponder];
}
connect action to button...and make sure that You have declared UITextFieldDelegate in .H file
Actually, I remember it now.
I need to use Touch Down with a type of id and call it backgroundTap. Thanks, myself. :P
I would recommend adding a UIGestureRecognizer to you background view. Like this
- (void)viewDidLoad {
[super viewDidLoad];
// Do whatever you want...
UITapGestureRecognizer *screenTapped = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(dismissKeyboard)];
screenTapped.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:screenTapped];
}
- (void)dismissKeyboard {
[self.view endEditing:YES];
}
Now the keyboard will be dismissed when the user taps the background view.
Hope it helps!
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.
I have a ViewController with a subview that contains a UISearchBar. When I click on the search bar the keyboard appears and I am able to close it using the cancel button. The problem seems to be that it isn't accepting any of the input when a user clicks on the keyboard buttons.
#pragma mark -
#pragma mark SEARCH METHODS
#pragma mark -
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
self.mainSearchBar.showsCancelButton = YES;
return YES;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
[self.mainSearchBar resignFirstResponder];
self.mainSearchBar.showsCancelButton = NO;
self.mainSearchBar.text = #"";
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self.mainSearchBar resignFirstResponder];
}
Has anyone had this issue before or know how to fix it?
** UPDATE *****
It turns out the Siri will work when trying to edit the UISearchBar. Still no luck with the keyboard input though. I think it has something to do with the fact that the UISearchBar is situated on a UIView that is then added as a subview. Not sure how to fix it though.
** UPDATE 2 *****
Moved the search box to the main UIView and I am still getting the same error. I am wondering if it is now related to the Navigation Controller.
Make sure that the app delegate has a [self.window makeKeyAndVisible]. Hopefully it will solve your problem.
Check whether you have added a UISearchBarDelegate in your viewController's .h file.
Try this code also:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
NSLog(#"%#",searchText);
}
This has to be related to how the SearchBar is rendered in relation to the ViewController's view. Why are you making the SearchBar a subview of another view rather than a subview of the ViewController's view?
Problem solved, the answer was found on a previous thread Keyboard and cursor show, but I can't type inside UITextFields and UITextViews
It turns out that in IOS6 the Visible at Launch check needs to be clicked on the options.
I need to keep track of which text field is the firstResponder for my custom keyboard to work. In the code below, I have grossly oversimplified my program, but here is the gist of the problem:
#implementation SimplePickerViewController
#synthesize pickerKeyboard;
#synthesize textView;
#synthesize textView2;
#synthesize firstResponder;
-(void)viewDidLoad{
pickerKeyboard = [[PickerKeyboardViewController alloc] initWithNibName:#"PickerKeyboard" bundle:nil];
pickerKeyboard.delegate = self;
[self.textView setInputView:pickerKeyboard.view];
[self.textView setDelegate:self];
[self.textView2 setInputView:pickerKeyboard.view];
[self.textView2 setDelegate:self];
}
-(void)hideKeyboard{
[self.firstResponder resignFirstResponder];
self.firstResponder = nil; //without this line, the code doesn't work.
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
self.firstResponder = textView;
[self.pickerKeyboard.picker reloadAllComponents];
return YES;
}
If I remove the line setting the firstResponder to nil, the code ceases to function properly, but I am not sure why. (Without that line, I can select the first textView to bring up the keyboard, but after that I can never bring the keyboard back. Any ideas? Thanks!
I'm not sure that I understand why firstResponder needs to be kept track of for a custom keyboard to work. I use a custom keyboard without knowing what the first responder is.
Do you use:
textView.inputView = pickerKeyboard
How about the following, called on the view to resign the first responder:
[self.view endEditing:NO];
I have had a similar problem and I have just figured out the issue. Somewhere in some part of Apple's first responder code, they are using a selector named firstResponder. When you created the property firstResponder you inadvertently overrode that selector. That will cause Apple's code to fail. This, in my humble opinion, is a bug in Apple's framework, and the firstResponder method isn't documented anywhere. Name your property myFirstResponder or anything else and everything should work just fine.
See Why does the keyboard not show when a view is popped from the navigation stack?