Преобразование UIKeyboardFrameEndUserInfoKey в View или Window Coordinates

Для константы UIKeyboardFrameEndUserInfoKey в документах Apple говорится:

Эти координаты не учитывают коэффициентов вращения применяется к содержимому окон в результате ориентации интерфейса изменения. Таким образом, вам может потребоваться преобразовать прямоугольник в окно координаты (с помощью метода convertRect: fromWindow: method) или для просмотра (используя метод convertRect: fromView:), прежде чем использовать его.

Итак, если я использую [view1 convertRect:rect fromView:view2]

Что бы я вложил для вышеуказанных параметров, чтобы заставить его правильно преобразовать значения вращения? то есть:

view1 =? rect =? (рамка клавиатуры, которую я предполагаю) view2 =?

Пробовал некоторые вещи и получал некоторые забавные вещи.

Ответ 1

Первое представление должно быть вашим видом. Второй вид должен быть равен нулю, то есть координаты окна/экрана. Таким образом:

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

Теперь у вас есть прямоугольник, который клавиатура займет, с точки зрения вашего вида. Если ваше представление представляет собой текущий вид контроллера контроллера (или его подвид), теперь учитываются вращение и т.д.

Ответ 2

Я попробовал принятый ответ и обнаружил, что на самом деле он не предоставляет CGRect клавиатуры в представлении. Я обнаружил, что мне нужно преобразовать CGRect из объекта UIScreen в объект UIWindow и из объекта UIWindow в объект UIView:

NSValue * keyboardEndFrame;
CGRect    screenRect;
CGRect    windowRect;
CGRect    viewRect;

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

Я использую приведенное выше, чтобы изменить размер корневого представления, чтобы оно не скрывалось клавиатурой:

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];

Ответ 3

+ (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);
}

Может использоваться как

- (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];
    }];
}