2010-05-23 2 views

ответ

31

Непрямой и безопасный SDK способ состоит в том, чтобы сделать текстовое поле первым ответчиком. Если внешняя клавиатура присутствует, местное уведомление UIKeyboardWillShowNotification не должно быть опубликовано.

Вы можете прослушать уведомление Darwin от "GSEventHardwareKeyboardAttached" (kGSEventHardwareKeyboardAvailabilityChangedNotification), но это частный API, поэтому ваше приложение будет отклонено, если вы его используете. Чтобы проверить наличие внешнего оборудования, воспользуйтесь частной функцией GSEventIsHardwareKeyboardAttached().

UIKit слушает это и соответственно устанавливает свойство UIKeyboardImpl.isInHardwareKeyboardMode, но опять же это частный API.

+4

Нет ли способ сделать это с публичными призывами?Когда мое приложение получает отклоненные виды поражений, цель написания его в первую очередь =) – carloe

+0

@carloe: Зачем вам это нужно в первую очередь? :) – kennytm

+0

Я вполне мог бы пойти по этому неправильному пути =) У меня есть UIView, который нужно расположить по-разному в зависимости от того, отображается ли на экране виртуальная клавиатура iPad ... – carloe

28

Существует еще один уровень.

  • Если у вас нет inputAccessoryView, вы не получите уведомление, как указано выше.
  • Однако, если вы настроили inputAccessoryView для текстового представления, вы все равно получите уведомление UIKeyboard, когда присутствует внешний kbd, - логика заключается в том, что вам нужно будет оживить ваше представление в нужном месте, чтобы вы нужна информация анимации, содержащаяся в уведомлении.

К счастью, информации достаточно, чтобы выяснить, будет ли представлен kbd, хотя он все еще немного связан.

Если мы рассмотрим словарь уведомления мы видим следующую информацию:

UIKeyboardFrameBeginUserInfoKey = NSRect: {{0, 1024}, {768, 308}} 
UIKeyboardFrameEndUserInfoKey = NSRect: {{0, 980}, {768, 308}} 

Это было в портретном; если повернуть устройство в PortraitUpsideDown мы получаем:

UIKeyboardFrameBeginUserInfoKey = NSRect: {{0, -308}, {768, 308}} 
UIKeyboardFrameEndUserInfoKey = NSRect: {{0, -264}, {768, 308}} 

Аналогично в LandscapeLeft и LandscapeRight мы получаем различные места начала и конца.

Хм ... что означают эти цифры? Вы можете видеть, что kbd выключен для запуска, но он немного движется. Чтобы ухудшить ситуацию, в зависимости от ориентации устройства, местоположения kbd различны.

Однако, у нас есть достаточно информации, чтобы выяснить, что происходит:

  1. The KBD движется от просто закадровый на физическом дне устройства на той же высоте, что и inputAccessoryView (но затемняется ею)
  2. Таким образом, в портрете портрета он перемещается от 1024 до 980 - у нас должен быть входной доступ к представлению с высотой 44, что действительно так.
  3. Итак, в портрете, если конец y + входной высоты окна высоты == высота экрана, то kbd не отображается. Вам нужно справиться с другими вращениями, но это идея.
+0

Это единственный способ достичь этого, если связан вход с именем AccessAccessoryView. Здесь стоит отметить iOS 8, они изменили способ, на котором установлено устройство. Каждый раз с любой ориентацией верхний левый угол равен (0,0). – cirronimbo

5

Даже используя inputAccessoryView в экземпляре UITextView, установленном экземпляром UIView с фреймом, CGRectZero работает, чтобы получить доставку уведомлений клавиатуры, работающих с аппаратной клавиатурой.

4

Это код, который я использую для получения высоты с клавиатуры userInfo в UIKeyboardWillShowNotification. Работает как с физической, так и с виртуальной клавиатурой.

NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]; 

CGRect keyboardRect = [aValue CGRectValue]; 

CGFloat deviceHeight = [UIScreen mainScreen].bounds.size.height; 
CGFloat deviceWidth = [UIScreen mainScreen].bounds.size.width; 

CGFloat newKeyboardHeight; 

if (interfaceOrientation == UIInterfaceOrientationPortrait) 
    newKeyboardHeight = deviceHeight - keyboardRect.origin.y; 
else if (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) 
    newKeyboardHeight = keyboardRect.size.height + keyboardRect.origin.y; 
else if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) 
    newKeyboardHeight = deviceWidth - keyboardRect.origin.x; 
else 
    newKeyboardHeight = keyboardRect.size.width + keyboardRect.origin.x; 
+0

Утверждение 'switch' будет более чистым. – Rivera

0

Следующий код дает рамку клавиатуры для всех ориентаций, используете ли Вы полный вид экрана или детальный вид зрения разделения.

NSDictionary* info = [aNotification userInfo]; 
CGRect frame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
CGRect keyboardEndFrame = [self.view convertRect:frame fromView:nil]; // The raw frame values are physical device coordinate. 
CGSize keyboardSize = keyboardEndFrame.size; 

Рамка клавиатура поставляется нотификацией всегда с точки зрения аппаратных координат с началом в верхнем правом углу экрана, когда устройство IOS в обычном портретном режиме с домашней кнопки в нижней части. Метод -convertRect: fromView меняет координаты из оконных координат (= hardware) на локальные координаты.

Я обнаружил, что с клавиатурой Bluetooth вы получаете один UIKeyboardDidShowNotification в первый раз, когда есть поворот экрана, но ни один после этого. Сложно отличить пристыкованную клавиатуру от разблокированных/разделенных и BT-клавиатур.

3

Основываясь на этой теме, я собрал два статических метода, которые можно легко вызывать из способов уведомления клавиатуры для обработки правильно изменения размера представления (обычно UIScrollViews), когда появляется клавиатура, независимо от типа (программное обеспечение против аппаратных средств):

+ (void)keyboardWillShowHide:(NSNotification *)notification 
        inView:(UIView *)view 
       adjustView:(UIView *)viewToAdjust 
{ 
    // How much should we adjust the view's frame by? 
    CGFloat yOffset = [SMKeyboardUtil keyboardOffsetForKeyboardNotification:notification 
                     inView:view]; 
    CGRect viewFrame = viewToAdjust.frame; 
    viewFrame.size.height -= yOffset; 

    // Get the animation parameters being used to show the keyboard. We'll use the same animation parameters as we 
    // resize our view. 
    UIViewAnimationCurve animationCurve; 
    NSTimeInterval animationDuration; 
    [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve]; 
    [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration]; 

    // Resize the view's frame to subtract/add the height of the keyboard (and any inputAccessoryView) 
    [UIView beginAnimations:@"animate resiz view" context:nil]; 
    [UIView setAnimationDuration:animationDuration]; 
    [UIView setAnimationCurve:animationCurve]; 
    [viewToAdjust setFrame:viewFrame]; 
    [UIView commitAnimations]; 

} 

+ (CGFloat)keyboardOffsetForKeyboardNotification:(NSNotification *)notification 
             inView:(UIView *)view 
{ 
    NSAssert(notification.userInfo[UIKeyboardFrameBeginUserInfoKey], @"Invalid keyboard notification"); 

    // Get the frame of keyboard from the notification 
    CGRect keyboardFrameBeginRaw = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue]; 
    CGRect keyboardFrameEndRaw = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; 

    // Because the frame we get from the notification is raw screen coordinates, without accounting for device orientation, 
    // we need to convert the frame to be relative to our view. 
    CGRect keyboardFrameBegin = [view convertRect:keyboardFrameBeginRaw fromView:nil]; 
    CGRect keyboardFrameEnd = [view convertRect:keyboardFrameEndRaw fromView:nil]; 

    // We could examine the size of the frame, but this does not account for hardware keyboards. Instead, 
    // we need to need the delta between the start and end positions to determine how much to modify 
    // the size of our view. 
    return keyboardFrameBegin.origin.y - keyboardFrameEnd.origin.y; 
} 
7

Основываясь на @ user721239, условие if определяет, находится ли нижняя часть клавиатуры вне рамки self.view. «convertRect» нормализует рамку для любой ориентации.

- (void)keyboardWillShow:(NSNotification *)notification { 
keyboardFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
keyboardFrame = [self.view convertRect:keyboardFrame fromView:nil]; // convert orientation 
keyboardSize = keyboardFrame.size; 
//NSLog(@"keyboardFrame.origin.y = %f", keyboardFrame.origin.y); 
//NSLog(@"keyboardFrame.size.height = %f", keyboardFrame.size.height); 
BOOL hardwareKeyboardPresent = FALSE;; 
if ((keyboardFrame.origin.y + keyboardFrame.size.height) > (self.view.frame.size.height+self.navigationController.navigationBar.frame.size.height)) { 
    hardwareKeyboardPresent = TRUE; 
} 
//NSLog(@"bottomOfKeyboard = %f", bottomOfKeyboard); 
//NSLog(@"self.view.frame.size.height = %f", self.view.frame.size.height); 
-3

Ответ на философский вопрос работал для меня. Решение является менее сложным по прошивке 8:

CGRect keyboardRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 

CGFloat deviceHeight = [UIScreen mainScreen].bounds.size.height;  
CGFloat keyboardHeight = deviceHeight - keyboardRect.origin.y; 

NSLog(@"actualKeyboardHeight = %f", keyboardHeight); 
+0

Что относительно ориентации? – Rivera

1

Поскольку большинство методов в предыдущих ответах устарели с прошивкой 8 и 9 я пересекаться с клавиатурой сообщили кадр с текущим окном, чтобы получить фактическую видимую рамку клавиатуры , Затем вы можете просто проверить, изменилась ли высота.

CGRect reportedKeyboardFrameRaw = [[[notification userInfo] valueForKey: UIKeyboardFrameEndUserInfoKey] CGRectValue]; 

CGRect reportedKeyboardFrame = [self.view.window convertRect: reportedKeyboardFrameRaw fromWindow:nil]; 

CGRect visibleKeyboardFrame = CGRectIntersection(reportedKeyboardFrame, self.view.window.frame); 

if (reportedKeyboardFrame.size.height != visibleKeyboardFrame.size.height) 
{ 
    // External keyboard present! 
} 
0

Это не прямой ответ для обнаружения, если внешняя клавиатура присутствует, но я делаю это, чтобы обнаружить фактическую высоту, необходимую для отображения просмотра (ов) клавиатуры, связанные в нижней части экран.

CGRect keyboardFrame = [[[notification userInfo] objectForKey:@"UIKeyboardFrameEndUserInfoKey"] CGRectValue]; 
CGFloat keyboardRelatedViewsHeight = self.view.window.frame.size.height - keyboardFrame.origin.y; 
2

Вы можете использовать следующее, которое также вычисляет высоту высоты клавиатуры/панели инструментов при подключении аппаратной клавиатуры. Вам нужно будет подписаться на уведомления KeyboardWillShow:

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

затем обрабатывать уведомление, как так:

- (void)keyboardWillShow:(NSNotification *)notification 
{  
    // Information we want to determine from notification 
    BOOL isHardwareKB = NO; 
    CGFloat keyboardHeight; 

    // Notification info 
    NSDictionary* userInfo = [notification userInfo]; 
    CGRect keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; 
    CGRect keyboard = [self.view convertRect:keyboardFrame fromView:self.view.window]; 
    CGFloat height = self.view.frame.size.height; 

    // Determine if hardware keyboard fired this notification 
    if ((keyboard.origin.y + keyboard.size.height) > height) { 
     isHardwareKB = YES; 
     keyboardHeight = height - keyboard.origin.y; // toolbar height 
    } else { 
     isHardwareKB = NO; 
     // As this value can change depending on rotation 
     keyboardHeight = MIN(keyboardFrame.size.width, keyboardFrame.size.height); 
    } 

    // adjust view ui constraints ext ext depending on keyboard height 
    // .... 
} 

Вы также можете обрабатывать уведомления KeyboardWillHide. Это будет пожар, когда первый ответчик для аппаратной и программной клавиатуры.

- (void)keyboardWillShow:(NSNotification *)notification 
{  
    // Information we want to determine from notification 
    BOOL isHardwareKB; // this is irrelevant since it is hidden 
    CGFloat keyboardHeight = 0; // height is now 0 

    // Do any view layout logic here for keyboard height = 0 
    // ... 
} 

Также не забудьте удалить наблюдателя:

-(void) dealloc { 
     [[NSNotificationCenter defaultCenter] removeObserver:self]; 
     [super dealloc]; 
} 
Смежные вопросы