23

I have a UIViewController presented using self.accountViewController.modalPresentationStyle = UIModalPresentationFormSheet; and now in iOS 8 the last UITextView is hidden from the keyboard when it will pushed up. How to avoid It?

FelixSFD
  • 6,052
  • 10
  • 43
  • 117
Alessio Crestani
  • 1,602
  • 4
  • 17
  • 38

3 Answers3

56

@Oleg's solution is good but it doesn't take into consideration keyboard changes in size while its already showing.. also, he hardcoded the animation duration and a few other parameters. See my solution below:

Add an observer of UIKeyboardWillChangeFrameNotification to the viewDidLoad

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

And then add the method:

- (void)keyboardFrameWillChange:(NSNotification *)notification
{
    CGRect keyboardEndFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGRect keyboardBeginFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    UIViewAnimationCurve animationCurve = [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
    NSTimeInterval animationDuration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] integerValue];

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:animationDuration];
    [UIView setAnimationCurve:animationCurve];

    CGRect newFrame = self.view.frame;
    CGRect keyboardFrameEnd = [self.view convertRect:keyboardEndFrame toView:nil];
    CGRect keyboardFrameBegin = [self.view convertRect:keyboardBeginFrame toView:nil];

    newFrame.origin.y -= (keyboardFrameBegin.origin.y - keyboardFrameEnd.origin.y);
    self.view.frame = newFrame;

    [UIView commitAnimations];
}

Don't forget to remove the keyboard observer in both viewDidUnload and in Dealloc.

Julian F. Weinert
  • 7,474
  • 7
  • 59
  • 107
newton_guima
  • 1,569
  • 2
  • 18
  • 26
  • How to handle the view when the keyboard gets hidden? – Sreejith Oct 08 '14 at 07:16
  • @Sreejith what do you mean? when the keyboard gets hidden the view comes back to the normal state. – newton_guima Oct 09 '14 at 22:45
  • @newton_guima yes..but I dont want the whole view to get pushed up.. can you please give an input to this question : http://stackoverflow.com/questions/26255151/ios-8-move-uiview-up-when-keyboard-appears-issue/ .. many thanks.. – Sreejith Oct 10 '14 at 03:04
  • @Sreejith this code can be applied to any view that you want to move along with the keyboard, just change the self.view code in "self.view.frame = newFrame;" to the view you want to be moved. – newton_guima Oct 18 '14 at 21:40
  • Thanks... Worked great – vinylDeveloper Dec 31 '14 at 20:53
  • Having problems with constraints and when using accessoryView. Can you please look at my question: http://stackoverflow.com/questions/29947592/get-keyboard-size-on-ios-8-not-working-with-external-keyboard – Sunkas Apr 30 '15 at 07:02
  • I love how this adjusts to the emoji keyboard, and others. However how are you dismissing the keyboard? I have a textView inside of a UIView and when I resignFirstResponder for my textView, it returns to its original position, but if I tap the textView again, it won't come above the keyboard again. I must be dismissing the keyboard incorrectly? Any help would be much appreciated. Thanks! – Joshua Hart Nov 10 '15 at 23:28
  • For me, I set the keyboard height as self.view's frame height as my self.view isn't UIScrollView. `newFrame.size.height -= (keyboardFrameBegin.origin.y - keyboardFrameEnd.origin.y);` Thanks all the same! – Itachi Jan 25 '16 at 08:57
  • I have 2 textfields one has Numpad keyboard but while switching from numpad keyboard textfield to Qwerty keyboard textfield the above methode not set proper distance between textfield and keyboard – SM18 Jul 04 '16 at 08:10
5

Swift Version of @newton_guima's answer above incase anyone wants it.

Add observer of UIKeyboardWillChangeFrameNotification to viewDidLoad():

NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardFrameWillChange:", name: UIKeyboardWillChangeFrameNotification, object: nil)

Then add this method:

func keyboardFrameWillChange(notification: NSNotification) {
    let keyboardBeginFrame = (notification.userInfo! as NSDictionary).objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue
    let keyboardEndFrame = (notification.userInfo! as NSDictionary).objectForKey(UIKeyboardFrameEndUserInfoKey)!.CGRectValue

    let animationCurve = UIViewAnimationCurve(rawValue: (notification.userInfo! as NSDictionary).objectForKey(UIKeyboardAnimationCurveUserInfoKey)!.integerValue)

    let animationDuration: NSTimeInterval = (notification.userInfo! as NSDictionary).objectForKey(UIKeyboardAnimationDurationUserInfoKey)!.doubleValue

    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(animationDuration)
    UIView.setAnimationCurve(animationCurve!)

    var newFrame = self.view.frame
    let keyboardFrameEnd = self.view.convertRect(keyboardEndFrame, toView: nil)
    let keyboardFrameBegin = self.view.convertRect(keyboardBeginFrame, toView: nil)

    newFrame.origin.y -= (keyboardFrameBegin.origin.y - keyboardFrameEnd.origin.y)
    self.view.frame = newFrame;

    UIView.commitAnimations()
}

Then remove the observer wherever you transition away from the view or in deinit:

NSNotificationCenter.defaultCenter().removeObserver(self)
Community
  • 1
  • 1
myles
  • 1,681
  • 1
  • 15
  • 27
3

For solving of you're problem you should change frame or constrain of the textview.

Small tip for you:

Use Notification to detect when keyboard will show or hide.

Sample of notification:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];

And than change the one of the parameters that are mention above.

Example of changing of frame:

- (void)keyboardWillHide:(NSNotification *)notification
{
    [self.view layoutIfNeeded];
    [UIView animateWithDuration:0.2
                     animations:^{
    [self setStartingFrame:self.commentsView.frame.size.height - commentViewOutlet_.frame.size.height - tabBarOffset_];
                         [self.view layoutIfNeeded];
                     }];
}
Oleg Gordiichuk
  • 15,240
  • 7
  • 60
  • 100
  • 1
    UIKeyboardWillShowNotification, UIKeyboardWillHideNotification - those notifications are not getting fired under iOS8 – ArturOlszak Dec 16 '14 at 23:03
  • My iOS8 fires them well – adnako Jan 06 '15 at 21:58
  • 1
    You should avoid using `UIKeyboardWillHideNotification` and `UIKeyboardWillShowNotification` because, starting in iOS 8, the keyboard can change size after it's been shown or hidden. You can consolidate all of your keyboard notification handlers into a single notification, `UIKeyboardWillChangeFrameNotification`. – Sean Michael Dorian May 26 '15 at 17:34