0

I know that this question is asked many times, but I can not figure out where am I making mistake. In simple words I can not implement it properly.

I have App which has to work on iPhone and iPad (in portrait orientation only). I have a subclassed UITextField. I need to move it up when it is hidden by keyboard during the edit. I can not set it properly, because the calculation of the size of the keyboard is done after it enters in the edit mode.

I know that I need following steps:

  1. Register observer
  2. Have routine that calculates Keyboard rectangle from which I can take height
  3. Have 2 events on show and hide of the keyboard to make offset of my custom text field.

Please tell me where I am wrong.

My code is:

Register observer:

- (id)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super initWithCoder:aDecoder]) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChange:) name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChange:) name:UIKeyboardDidShowNotification object:nil];
        _leftInlineImage = NO;
    }
    return self;
}

Calculating keyboard height:

- (void)keyboardWillChange:(NSNotification *)notification {
    NSDictionary* d = [notification userInfo];
    CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    r = [self.superview convertRect:r fromView:nil];
    _keyboardHeight = r.size.height;
}

Show/hide keyboard:

/* Move keyboard */
-(void)showKeyboardWithMove {

    CGRect screenRect = [[UIScreen mainScreen] bounds];
    ////CGFloat screenWidth = screenRect.size.width;
    CGFloat screenHeight = screenRect.size.height;

    //_keyboardHeight = KEYBOARD_HEIGHT;

    if (self.frame.origin.y + self.frame.size.height > screenHeight - _keyboardHeight) {
        double offset = screenHeight - _keyboardHeight - self.frame.origin.y - self.frame.size.height;
        CGRect rect = CGRectMake(0, offset, self.superview.frame.size.width, self.superview.frame.size.height);

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.3];

        self.superview.frame = rect;

        [UIView commitAnimations];
    }

}

-(void)hideKeyboardWithMove {

    CGRect rect = CGRectMake(0, 0, self.superview.frame.size.width, self.superview.frame.size.height);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];

    self.superview.frame = rect;

    [UIView commitAnimations];

}

The calculation is made before and my height is 0. All this is done in the subclass of the UITextField.

new2ios
  • 1,350
  • 2
  • 25
  • 56
  • 1
    possible duplicate of [How to get UIKeyboard size with Apple iPhone SDK](http://stackoverflow.com/questions/3546571/how-to-get-uikeyboard-size-with-apple-iphone-sdk) – Chan Dec 02 '14 at 09:35
  • 1
    I know that this is duplicate @Chan, but I can not implement it, this is why I ask that question. – new2ios Dec 02 '14 at 09:38
  • But in order for the keyboard to appear, an editable UI element, needs to get focus. So I don't understand why the confusion ? – Lefteris Dec 02 '14 at 09:42
  • please check this answer: http://stackoverflow.com/questions/23988866/how-do-i-resize-views-when-keyboard-pops-up-using-auto-layout/23992055#23992055 – holex Dec 02 '14 at 09:49
  • I am sorry @Lefteris, but I don't understand your remark. Of course first the text field must get focus. My problem is when it gets focus `showKeyboardWithMove` is called and after that `keyboardWillChange`, which results in keyboard height = 0, i.e. I am doing nothing. – new2ios Dec 02 '14 at 09:54
  • 10x @holex, I am checking your answer. – new2ios Dec 02 '14 at 09:54

2 Answers2

4

Add an observer of UIKeyboardWillChangeFrameNotification to the viewDidLoad;

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

This method will help you :

- (void)keyboardFrameDidChange:(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];
}
Oleg Gordiichuk
  • 15,240
  • 7
  • 60
  • 100
  • Your solution is working. I only want to make one remark - it always move entire screen which can be a problem if your control is at the top. So some check must be made. My mistake was that I want to achieve my goal into the subclass of UITextField. – new2ios Dec 02 '14 at 13:23
  • This solution works great on iOS 8 but in iOS 7 keyboardFrameEnd and keyboardFrameBegin ended up having some crazy negative/incorrect values. I found that if I changed the convertRect call to the fromView: variant it started working on both. – Jon C Dec 08 '14 at 00:52
3

that gives you back the height of the keyboard.

NSNotification * note = // ... the notification you receive via UIKeyboardWillShowNotification
id _obj = [note.userInfo valueForKey:@"UIKeyboardBoundsUserInfoKey"];
CGRect _keyboardBound = CGRectNull;
if ([_obj respondsToSelector:@selector(getValue:)]) [_obj getValue:&_keyboardBound];

the _keyboardBound will have the correct size.


NOTE: that is not a full implementation to handle the keyboard's appearance, if you need the complex idea, please check my complete and accepted answer here (stackoverflow.com internal link).

Community
  • 1
  • 1
holex
  • 23,961
  • 7
  • 62
  • 76