13

I can handle two events: when keyboard shows and when keyboard hides. Everything worked fine in iOS 8.2 and older.

But how to handle event when you change your keyboard language? When you change the english keyboard to the emoji keyboard, the height of emoji keyboard (in ios 8.3) is bigger and it hides the content.

Or maybe you have a solution how to control iOS 8.3 emoji keyboard height? enter image description here

brandonscript
  • 68,675
  • 32
  • 163
  • 220
Albert
  • 161
  • 1
  • 5
  • 3
    Check out `UIKeyboardWillChangeFrameNotification`/`UIKeyboardDidChangeFrameNotification`. These are fired each time the keyboard frame changes, irrespective of the fact whether keyboard is hiding or not. For example, changing keyboard types (ascii/emoji) or toggling predictive text bar above the keyboard. – n00bProgrammer Apr 28 '15 at 17:44
  • OK. Let me update my Xcode and simulators and, i'll give you an optimized working solution. Give me an hour or so. – n00bProgrammer Apr 29 '15 at 09:58

4 Answers4

13

OK. So looking at my old code, I remembered, I do not use 2 observers (UIKeyboardDidShowNotification/UIKeyboardDidHideNotification). I use a single observer (UIKeyboardWillChangeFrameNotification), that is fired of each event: Keyboard hiding, keyboard showing, keyboard changing frame.

In my case, the text box and send button are in nested in a UIView and this is view is added in the view of the UIViewController, above everything else.

I add the observer in viewDidAppear and remove the observer in viewWillDisappear.(to avoid any notification firing when view is not active).

The above information is not necessary for your case, just added it for information sake. Relevant code is as follows:

ADD OBSERVER:

- (void) viewDidAppear:(BOOL)animated {

    [super viewDidAppear:animated];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
}

HANDLE NOTIFICATION:

- (void) keyboardWillChangeFrame:(NSNotification*)notification {

    NSDictionary* notificationInfo = [notification userInfo];

    CGRect keyboardFrame = [[notificationInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    [UIView animateWithDuration:[[notificationInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]
                          delay:0
                        options:[[notificationInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue]
                     animations:^{

                         CGRect frame = self.textViewContainer.frame;
                         frame.origin.y = keyboardFrame.origin.y - frame.size.height;
                         self.textViewContainer.frame = frame;

                     } completion:nil];
}

You might have to make a few adjustments to the frame.origin.y... line for correct calculations. I don't know whether you have a UITabBarController or any bars at the bottom. The safest bet here would be:

frame.origin.y = self.view.frame.size.height - keyboardFrame.size.height - X;

Where X is 0 if your VC covers the whole screen. If not, use the heights of any bottom bars.

n00bProgrammer
  • 4,261
  • 3
  • 32
  • 60
  • The layout constraints will need updating in that case. – n00bProgrammer Apr 29 '15 at 12:16
  • While remus provided a correct answer as well, this one is correct and easier to implement / less code. Works perfectly. – user3344977 Jul 18 '15 at 20:09
  • Yeah, but how does it dismiss the Keyboard afterwards. I enabled tap gestures to dismiss and it still stays right above where the keyboard used to be....can you please help me? – Joshua Hart Nov 10 '15 at 22:08
6

I had the same problem. Just replace UIKeyboardFrameBeginUserInfoKey with UIKeyboardFrameEndUserInfoKey . :-)

It worked for me.

Ankush
  • 2,405
  • 3
  • 22
  • 45
4

It's worth noting that the emoji keyboard is the same hight as the standard keyboard with suggested text enabled.

To properly determine keyboard height and adjust your view, add these observers:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];

Then I use the following methods to animate the keyboard adjustment. Really all you need is the keyboardBounds object, but if you happen to be using AutoLayout, this is how you'd do it:

- (void)keyboardDidShow:(NSNotification *)notification
{
    [self scrollControlBarTo:notification up:YES];
}

-(void)keyboardDidHide:(NSNotification *)notification
{
    [self scrollControlBarTo:notification up:NO];
}

- (void)scrollControlBarTo:(NSNotification *)notification up:(BOOL)up
{
    [_keyboardControlsBar layoutIfNeeded];
    CGRect keyboardBounds;
    NSDictionary *info = [notification userInfo];
    NSNumber *number = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    double duration = [number doubleValue];
    [[info objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardBounds];
    UIViewAnimationCurve curve = [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];

    [UIView animateWithDuration:duration
                          delay:0
                        options:UIViewAnimationOptionBeginFromCurrentState
                     animations:^{
                         [UIView setAnimationCurve:curve];
                         _keyboardControlsBarBottomConstraint.constant = (up) ? keyboardBounds.size.height : 0;
                         [self.view layoutIfNeeded];
                     } completion:nil];
}
brandonscript
  • 68,675
  • 32
  • 163
  • 220
  • Is it possible to determine the keyboard animation time too?? That would be the perfect! – Dunes Buggy Apr 28 '15 at 17:44
  • http://stackoverflow.com/questions/1419221/what-is-the-iphones-default-keyboard-animation-rate - updated my answer to include the relevant bits. – brandonscript Apr 28 '15 at 17:45
  • 1
    See http://stackoverflow.com/questions/18957476/ios-7-keyboard-animation for discussion on iOS 7's undocumented animation curve for keyboard animations. – jszumski Apr 28 '15 at 17:50
  • Nice one @jszumski - updated answer with what appears to be the simplest implementation of that. – brandonscript Apr 28 '15 at 18:01
0

Code above but in swift:

func viewDidAppear(_ animated: Bool) {

    super.viewDidAppear(animated)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChangeFrame(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}

...

func keyboardWillChangeFrame(_ notification: Notification?) {

let notificationInfo = notification?.userInfo

let keyboardFrame = notificationInfo?[UIResponder.keyboardFrameEndUserInfoKey]?.cgRectValue

UIView.animate(withDuration: TimeInterval((notificationInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.floatValue ?? 0.0), delay: 0, options: UIView.AnimationOptions(rawValue: (notificationInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber)?.intValue ?? 0), animations: {

    let frame = self.textViewContainer.frame


     frame.origin.y = (keyboardFrame?.origin.y ?? 0.0) - frame.size.height
        self.textViewContainer.frame = frame

    })
}