UIKeyboardWillHide not triggered - iphone

I read many post here about this topic, but I wasn't able to find an answer to my question, so, hope you won't be bored about another UIKeyboard post :-)
In my view controller's implementation I added self as an observer for the two notifications UIKeyboardWillShowNotification and UIKeyboardWillHideNotification, passing the selectors keyboardWillShow: and keyboardWillHide: to handle to notifications. As I touch a UITextField, the keyboardWillShow: method is called but when I press a "Done" button (which dismisses the keyboard) the keyboardWillHide: method is not called.
Really, I'd like to make my UITextField show a keyboard with the "hide button" on the bottom right of the keyboard, but I wasn't able to find the right keyboard type. Maybe I need to set the textfield retuntype to "...Done". In that way I saw that "return" key turns to "done".
So I set a toolbar to be my UITextField's inputAccessoryView, so now I can show a standard keyboard with a tool bar above with the "Done" button. As a user touches that button, I hide the keyboard with the resignFirstResponder method.
The strange thing is that when I call resignFirstResponder, the UIKeyboardWillHideNotification isn't posted; at least the keyboardWillHide: method is not called.
What do you suggest to me? I really wanted to display a keyboard with the small button with the down arrow to hide the keyboard, but also this solution could be right, but I'd like to resize the view and to do this I need to observer UIKeyboardWillHideNotification.
Thank you very much for help...
(ADDED:)
In viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:[[self view] window]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:[[self view] window]];
I took these declarations from one of "yours" post :-) But the willShow works...
The action of the "Done" button that's in the UIToolbar that's assigned to be the inputAccessoryView of my text field is:
-(void)keyboardDone {
[msgTextField resignFirstResponder];
CLOSED:
OK! When a developer is stupid... it is stupid :-) :-)
This is my corrected willHide method:
-(void)keyboardWillHide:(NSNotification*)n {
NSDictionary* userInfo;
CGSize keyboardSize;
CGRect viewFrame;
/* This was the bad guy :) I forgot to delete it
* after I previously copied the willShow method that
* checks if keyboard is already shown (if so returns).
*
* if( keyboardIsShown )
* return;
*/
userInfo = [n userInfo];
keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
viewFrame = [[self scrollView] frame];
viewFrame.size.height += ( keyboardSize.height - TABBAR_HEIGHT );
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.5];
[[self scrollView] setFrame:viewFrame];
[UIView commitAnimations];
keyboardIsShown = NO;
NSLog(#"HIDE\n");
}
First of all I'd like to thank you all for this useless work in helping me. I'd like to give you some points, so I'll try to rise a "interest point" for each answer, but I need to choose the right one... hard part... :-)
Excuse me again... I really didn't see the if() statement...

If you read the documents for UIWindow it says that the notification object for these notifications is nil. You are passing self.view.window in as the object to the addObserver:selector:name:object: method. Try passing nil instead:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];

It's important to note that when the user hides the software keyboard via the hide button, the hide methods aren't called. The show methods are called again, but the keyboard is nearly off screen except for the home row toolbar.

Check, if keyboardDone really gets called (i.e. with NSLog(#"%#", #"keyboard done called");). If its get called, but resignFirstResponder does not help dismissing the keyboard, then try this:
[self.view endEditing:YES];
Please also provide your keyboardWillHide: method.

To set the keyboard up so that it has a "Done" button, do this:
1) Setup your view controller so that it implements the UITextFieldDelegate. For Example:
#import <UIKit/UIKit.h>
#interface TX_ViewController : UIViewController <UITextFieldDelegate>
#property (nonatomic, retain) IBOutlet UITextField *textField;
#end
2) In your view controllers implementation file, use the following code to setup the keyboard:
- (void)viewDidLoad
{
[self.textField setDelegate:self];
[self.textField setReturnKeyType:UIReturnKeyDone];
[self.textField addTarget:self action:#selector(textFieldFinished:) forControlEvents:UIControlEventEditingDidEndOnExit];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
3) And if you wish to do something when the DONE button is pressed, simply add the following function to your view controller's implementation file:
- (IBAction)textFieldFinished:(id)sender
{
[sender resignFirstResponder];
}
Also, if you are using Interface builder to create your interfaces, don't forget to setup your IBOutlet reference for the TextField; otherwise, your class won't receive the messages from the XIB.
I set this up in a sample application just to see if it works and it did perform in the way you wish for your application to perform.

Swift $
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
func keyboardWillHide(notification: NSNotification){
print("keyboardWillHide")
}

Related

IPhones- Have the keyboard slide out with the view

We have a view open with keyboard shown , but when the back button clicked , the view slide out from right while the keyboard will slide only when the view disappeared.
if we call resignFirstResponder at viewwilldisappear, the view slide to the right while keyboard slide down at same time.
Is it possible to let the keyboard slide out with the view?
I have tested this and it works in iOS 5.1, however, I don't think this is recommended behaviour.
for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows])
if ([[keyboardWindow description] hasPrefix:#"<UITextEffectsWindow"]) {
NSLog(#"%#", [keyboardWindow description]);
[UIWindow beginAnimations:#"fadeKeyboard" context:nil];
keyboardWindow.frame = CGRectMake(keyboardWindow.frame.origin.x + keyboardWindow.frame.size.width, keyboardWindow.frame.origin.y, keyboardWindow.frame.size.width, keyboardWindow.frame.size.height);
[UIWindow commitAnimations];
}
You can also use a notification UIKeyboardWillHideNotification to detect when the keyboard is going to hide, or just use the above code manually.
There is no standard way to do what you want, but...
Basically, keyboard is just a view, presented in it's own UIWindow on top of all your other windows.
So, theoretically, what you need to do is to find keyboard view and move it in desired direction. I think you should use transform property and don't mess up with frame.
Class keyboardClass = NSClassFromString(#"UIPeripheralHostView");
for ( UIWindow *window in [[UIApplication sharedApplication] windows] ) {
for ( UIView *subview in window.subviews ) {
if ( [subview isKindOfClass:keyboardClass] ) {
// that's keyboard
}
}
}
Edited:
If you're talking about UINavigationController and it's default slide animations during push / pop, then, you just need to invoke resignFirstResponder in viewDidDisappear and becomeFirstResponder in viewWillAppear on your text view. That way your keyboard will slide along with your view.
Try sticking resignFirstresponder in the viewDidDisappear method instead.
**Set notificatins and use these methods.....Hope it solve problem:
First of all set your whole view in scrollView**
-(void)keyboardDidHide:(NSNotification *)notif
{
NSTimeInterval duration = 0.4;
[UIView animateWithDuration:duration animations:
^{
scrollView.contentSize=CGSizeMake(320,scrollOriginalFrame.size.height);
}];
keyboardVisible=NO;
}
-(void)keyboardDidShow:(NSNotification *)notif
{
scrollView.contentSize=CGSizeMake(self.view.frame.size.width, scrollOriginalFrame.size.height+235);
NSTimeInterval duration = 0.4;
[UIView animateWithDuration:duration animations:
^{
[scrollView setContentOffset:CGPointMake(0,162) animated:YES];
}];
keyboardVisible=YES;
}
**In viewDidLoad() add this**
//keyboard
scrollOriginalFrame=self.view.frame;
scrollOriginalFrame.size.height-=103;
scrollView.contentSize=scrollOriginalFrame.size;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(keyboardDidHide:) name:UIKeyboardWillHideNotification object:nil];
keyboardVisible=NO;

Having trouble hiding keyboard using invisible button which sits on top of uiscrollview

I have 3 items in play...
1) UIView sits at the base of the hierarchy and contains the UIScrollview.
2) UIScrollview that is presenting a lengthy user form.
3) An invisible button on the UIScrollview that I'm using to provide "hide the keyboard" features.
Notice in the code below that I'm registering to be notified when the keyboard is going to appear and again when it's going to disappear. These are working great.
My problem is seemingly one of "layers". See below where I insert the button into the view atIndex:0. This causes the button to be activated and "stuffed" behind the scrollview so that when you click on it, the scrollview grabs the touch and the button is unaware. There is no way to "reach" the button and suppress the keyboard.
However, if I insert atIndex:1, the button gets super imposed on top of the text entry fields and so any touch at all is acted upon by the button, which immediately suppresses the keyboard and then disappears.
How do I insert the button on top of the UIScrollview but behind the UITextfields that sit there?
other logistics: I have a -(void) hidekeyboard function that I have setup with the UIButtion as an IBAction(). And I have the UIButton connected to "files owner" via a ctrl-drag/drop. (Do I need both of those conventions?)
This code in ViewDidLoad()...
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification object:nil queue:nil usingBlock:^(NSNotification *notification){
[self.view insertSubview:self.keyboardDismissalButton atIndex:0];
}];
Here's a nifty way to do this without even needing the invisible button. This approach will only work on devices north of 3.2, but since we're already using the block methods on NSNotificationCenter, we know that we're at least at 4.0.
In lieu of a button, we instead add a tap gesture recognizer to our view. This tap gesture recognizer calls -dismissKeyboard: and then we ask our view to end all editing. This method is only available on 3.2 and later and works through it's subviews until it locates the current firstResponder and sends it -resignFirstResponder. The boolean argument that -endEditing: takes determines whether the resignation of firstResponder is forced or not. The documentation is a little vague, but I take it to mean that if forced, the -textFieldShouldEndEditing delegate method on UITextField will not be called.
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification object:nil queue:nil usingBlock:^(NSNotification *notification) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:tap];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillHideNotification object:nil queue:nil usingBlock:^(NSNotification *notification) {
[self.view removeGestureRecognizer:[self.view.gestureRecognizers lastObject]];
}];
}
- (void)dismissKeyboard:(UIGestureRecognizer *)gesture
{
[self.view endEditing:NO];
}
There is no way to have a view be in front of a sibling but behind the sibling's children. You can insert the button as a child of the scroll view (behind all the text fields), or you can override pointInside:withEvent: on the upper view to return false where it is over a text field and true otherwise (effectively "punching holes" in it).
Figured it out....
Here is the answer.
The code below is all within the ViewDidLoad() of the UIViewController. Begin by removing the button altogether from the UIView. (it will be rendered when the keyboard is activated).
Notice in the keyboard "WillShow" notification below that I am inserting the button onto my UIScrollView layer rather than the UIView layer, as before. However, once the button is clicked and the keyboard is about to be dismissed, I remove the button altogether from the UIView (i.e. self).
[self.keyboardDismissalButton removeFromSuperview];
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillShowNotification object:nil queue:nil usingBlock:^(NSNotification *notification){
[theScroller insertSubview:self.keyboardDismissalButton atIndex:0];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillHideNotification object:nil queue:nil usingBlock:^(NSNotification *notification){
[self.keyboardDismissalButton removeFromSuperview];
}];

How to set Custom keyboard specific to only a UItextfield

How to set Custom keyboard specific to only a UITextField? When I am changing using this method, all the keyboards in my application are changed to this new custom keyboard. I added:
[[NSNotificationCenter defaultCenter] addObserver:self.view
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
in a UIViewController. But after going to that UIView, keyboards in other UIViewControllers also look like new custom keyboard. How can i limit the custom keyboard to only one UIView? Please help me. Thanks in advance.
UITextField* textField;
UIView* customKeyboard;
textField.inputView = customKeyboard;
Similar thread: iPad custom Keyboard GUI
If you subclassed UITextView (as that tutorial shows), then all instances of that subclass will use the toolbar with a dismiss button.
If you don't want the toolbar, then don't use the subclass, just use the original UITextView.
You can try checking for the textfield that you want on the textFieldShouldBeginEditing like so:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (textField == YOUR_DESIRED_TEXTFIELD) {
[self openCustomKeyboard];
}
return YES;
}
My problem was once am loading custom keyboard, it remains everywhere in other UIviews of application. So i checked existence of UIToolbar in other UIkeyboard subviews and removed . Now its working fine..
for(UIView* keyboardToolbar in [keyboard subviews]){
if([[keyboardToolbar description] hasPrefix:#"<UIToolbar"] == YES)
{
[keyboardToolbar removeFromSuperview];
}
}

Custom Keyboard (iPhone), UIKeyboardDidShowNotification and UITableViewController

On an iPhone App, I've got a custom keyboard which works like the standard keyboard; it appears if a custom textfield becomes first responder and hides if the field resigns first responder. I'm also posting the Generic UIKeyboardWillShowNotification, UIKeyboardDidShowNotification and their hiding counterparts, like follows:
NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:5];
[userInfo setObject:[NSValue valueWithCGPoint:self.center]
forKey:UIKeyboardCenterBeginUserInfoKey];
[userInfo setObject:[NSValue valueWithCGPoint:shownCenter]
forKey:UIKeyboardCenterEndUserInfoKey];
[userInfo setObject:[NSValue valueWithCGRect:self.bounds]
forKey:UIKeyboardBoundsUserInfoKey];
[userInfo setObject:[NSNumber numberWithInt:UIViewAnimationCurveEaseOut]
forKey:UIKeyboardAnimationCurveUserInfoKey];
[userInfo setObject:[NSNumber numberWithDouble:thisAnimDuration]
forKey:UIKeyboardAnimationDurationUserInfoKey];
[[NSNotificationCenter defaultCenter] postNotificationName:UIKeyboardWillShowNotification
object:nil
userInfo:userInfo];
This code is working and I use it in UIViewController subclasses.
Now since iPhone OS 3.0, UITableViewController automatically resizes its tableView when the system keyboards show and hide. I'm only now compiling against 3.0 and I thought that the controller should also resize the table if my custom keyboard appears, since I'm posting the same notification. However it doesn't. The table view controller is set as the delegate of the input fields.
Does anyone have an idea why this might be the case? Has anyone implemented something similar successfully?
I have standard input fields along the custom ones, so if the user changes the fields the standard keyboard hides and the custom one shows. It would be beneficial if the tableView didn't resize to full height and I didn't have to resize it back with a custom method.
Well there are a few possibilities that you poke around in. From your description, it seems that UITableView is not using the UIKeyboard Notifications.
But possibly, it is the UINavigationController that is responding to this notification (or UITabBarController).
You could override methods like setFrame: drawRect: and setNeedsDisplay in the tableview to see what is happening in the call stack. You may be able to figure out what is actually causing the tableview to redraw at the correct size.
But in all likelihood, just changing the size of the tableView yourself is the much easier solution. These suggestions are just for fun!
I have done something similar. If I recall, I ended up just having the TableViewController subecibe to the notifications that either you send or the system sends, and then animate the change to the tableview's frame. Presumably there are doing something similar internally, but I think the end result just becomes two animation blocks wrapped around each other that both run when the system is posting the notifications, but the end result should be the same.
In your viewdidLoad:
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardWillShow:)
name: UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardDidShowOrHide:)
name: UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardWillHide:)
name: UIKeyboardWillHidewNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(keyboardDidShowOrHide:)
name: UIKeyboardDidHideNotification object:nil];
and in the view controller:
-(void) keyboardWillShow:(id)sender {
[UIView beginAnimations];
[UIView setAnimationDuration:0.3];
self.view.frame = //Your new size
}
-(void) keyboardDidShowOrHide:(id)sender {
[UIView commitAnimations];
}
-(void) keyboardWillHide:(id)sender {
[UIView beginAnimations];
[UIView setAnimationDuration:0.3];
self.view.frame = //Your old size
}

iPhone SDK: handling keybaord appearance

I need to move UI elements of my view controller when keyboard appears. I do this by registering for the keyboard notifications in my app delegate:
[[NSNotificationCenter defaultCenter] addObserver:observer
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:observer
selector:#selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification object:nil];
and then handling notification as prescribed by Apple (I have similar code for keyboard was shown) to scroll the view up and down:
- (void)keyboardWasHidden:(NSNotification*)aNotification
{
CGRect viewFrame = [self.view frame];
viewFrame.origin.y += keyboardSize.height - TOOLBAR_HEIGHT;
self.view.frame = viewFrame;
}
So far so good. Now problem description:
When I execute this code to show OS 3.0 specific message UI:
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[self presentModalViewController:picker animated:YES];
and when keyboard shows in the actual mail UI, I still get keyboard notification which scrolls my view and therefore breaking my UI (note that mail controller takes entire screen and my view is not even visible at this point).
I was hoping to temporary disable keyboard notification, so my scrolling code would not get called with this line:
[[NSNotificationCenter defaultCenter] removeObserver:self];
But it does not help, keyboard even still get posted.
What should I do avoid reacting on the keyboard when it created by the message UI?
Add a BOOL property or instance variable: careAboutKeyboard that's accessible to both your keyboardWasShown: and keywardWasHidden: methods, likely in the view controller those methods are in.
Have it set to YES when in the viewWillAppear method, and set to NO when you show the mail view and in viewWillDisappear.
Then put all of your scrolling logic in an if block:
if(careAboutKeyboard) {
// Scrolling logic
}