Convert UIKeyboardFrameEndUserInfoKey to View or Window Coordinates

前端 未结 3 2196
灰色年华
灰色年华 2020-12-14 01:15

For the constant UIKeyboardFrameEndUserInfoKey, in the Apple docs it says:

These coordinates do not take into account any rotation facto

相关标签:
3条回答
  • 2020-12-14 01:53

    I tried the accepted answer and found that it does not actually provide the CGRect of the keyboard within the view. I found that I have to convert the CGRect from the UIScreen object to the UIWindow object, and from the UIWindow object to the UIView object:

    NSValue * keyboardEndFrame;
    CGRect    screenRect;
    CGRect    windowRect;
    CGRect    viewRect;
    
    // determine's keyboard height
    screenRect    = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    windowRect    = [self.view.window convertRect:screenRect fromWindow:nil];
    viewRect      = [self.view        convertRect:windowRect fromView:nil];
    

    I use the above to resize the root view to not be hidden by the keyboard:

    NSTimeInterval  duration;
    CGRect          frame;
    
    // determine length of animation
    duration  = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    
    // resize the view
    frame              = self.view.frame;
    frame.size.height -= viewRect.size.height;
    
    // animate view resize with the keyboard movement
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:duration];
    self.view.frame = frame;
    [UIView commitAnimations];
    
    0 讨论(0)
  • 2020-12-14 01:58
    + (void)parseKeyboardNotification:(NSNotification *)notification
                     inRelationToView:(UIView *)view
                                 info:(void(^)(NSTimeInterval keyboardAnimationDuration, CGRect keyboardFrameInView, UIViewAnimationOptions keyboardAnimationOptions))callback
    {
        NSParameterAssert(notification != nil);
        NSParameterAssert(view != nil);
    
        NSDictionary *userInfo = [notification userInfo];
    
        UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
        UIViewAnimationOptions animationOption = animationCurve << 16; // https://devforums.apple.com/message/878410#878410
        NSTimeInterval animationDuration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    
        // http://stackoverflow.com/a/16615391/202451
        CGRect screenRect    = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
        CGRect windowRect    = [view.window convertRect:screenRect fromWindow:nil];
        CGRect viewRect      = [view        convertRect:windowRect fromView:nil];
    
        callback(animationDuration, viewRect, animationOption);
    }
    

    Can be used like this

    - (void)keyboardWillShowOrHide:(NSNotification *)notification
    {    
        [AGKeyboardInfo parseKeyboardNotification:notification inRelationToView:self.view info:^(NSTimeInterval keyboardAnimationDuration, CGRect keyboardFrameInView, UIViewAnimationOptions keyboardAnimationOptions) {
    
            [UIView animateWithDuration:keyboardAnimationDuration delay:0 options:keyboardAnimationOptions animations:^{
    
                 // do any modifications to your views
    
            } completion:nil];
        }];
    }
    
    0 讨论(0)
  • 2020-12-14 02:12

    The first view should be your view. The second view should be nil, meaning window/screen coordinates. Thus:

    NSDictionary* d = [notification userInfo];
    CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    r = [myView convertRect:r fromView:nil];
    

    Now you have the rect that the keyboard will occupy, in terms of your view. If your view is the current view controller's view (or a subview thereof), rotation and so forth are now accounted for.

    0 讨论(0)
提交回复
热议问题