如果连接了硬件键盘,则隐藏inputAccessoryView

时间:2015-01-08 00:00:42

标签: ios keyboard

与此问题类似:iPad: Detecting External Keyboard,我正在开发一个iPad应用程序,该应用程序使用带有自定义inputAccessoryView的文本字段来为虚拟键盘提供其他功能。

但是,如果硬件键盘(例如蓝牙键盘)连接到设备,则软件键盘未按预期显示,但由于某种原因,inputAccessoryView 仍然可见在屏幕的底部。此外,这似乎导致触发UIKeyboardDidShowNotification(因此,即使硬件键盘用于输入,也可以移动我的视图以避免键盘实际上不存在遮挡)。

我找到了几种解决方案来检测硬件键盘是否已连接,但是所有这些都在接收到UIKeyboardDidShowNotification后检查状态,此时inputAccessoryView已经可见(例如{ {3}})。

如果没有连接硬件键盘,我正在寻找一种只显示inputAccessoryView的方法。因此,我需要知道是否连接了硬件键盘之前 UIKeyboardDidShowNotification被触发。

此处提供的已接受解决方案How can I detect if an external keyboard is present on an iPad?对我来说无处可选,因为他们使用的私有API可能导致我的应用被拒绝。

3 个答案:

答案 0 :(得分:4)

这只是@arlomedia对答案的增强。我所做的是关注willShow和didShow。

我使用的willShow将我的textview移动到位,使其以与键盘相同的速度移动。

我使用上述技术检查键盘表观大小的didShow,并相应地隐藏/显示accessoryInputView。

非常重要我还默认将该视图设置为隐藏,并且当收到一个willHide事件时,它会再次被隐藏。

- (void) addKeyboardObserver {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHidden:) name:UIKeyboardWillHideNotification object:nil];
}

- (void) removeKeyboardObserver {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification*)notification {
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    // If we're on iOS7 or earlier and landscape then the height is in the
    // width.
    //
    if ((IS_LANDSCAPE == YES) && (IS_IOS8_OR_LATER == NO)) {
        keyboardSize.height = keyboardSize.width;
    }

    NSNumber *rate = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey];

    CGRect textFieldFrame = self.textField.frame;
    textFieldFrame.origin.y = ([Util screenHeight] - keyboardSize.height) - textFieldFrame.size.height - [Util scaledHeight:10.0];

    // Move the text field into place.
    //
    [UIView animateWithDuration:rate.floatValue animations:^{
        self.answerTextField.frame = textFieldFrame;
    }];

    keyboardShown = YES;
}

- (void)keyboardDidShow:(NSNotification*)notification {
    CGRect keyboardBeginFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGRect keyboardEndFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGSize keyboardSize = keyboardBeginFrame.size;

    // If we're on iOS7 or earlier and landscape then the height is in the
    // width.
    //
    if ((IS_LANDSCAPE == YES) && (IS_IOS8_OR_LATER == NO)) {
        keyboardSize.height = ABS(keyboardBeginFrame.origin.x - keyboardEndFrame.origin.x); // the keyboard will move by an amount equal to its height when it appears; ABS is needed for upside-down orientations
    } else {
        keyboardSize.height = ABS(keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y); // the keyboard will move by an amount equal to its height when it appears; ABS is needed for upside-down orientations
    }

    NSNumber *rate = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey];

    [UIView animateWithDuration:rate.floatValue animations:^{
        if (keyboardSize.height <= self.accessoryBar.frame.size.height) {
            self.textField.inputAccessoryView.hidden = YES;
            self.answerTextField.inputAccessoryView.userInteractionEnabled = NO;
        } else {
            self.textField.inputAccessoryView.hidden = NO;
            self.answerTextField.inputAccessoryView.userInteractionEnabled = YES;
        }
    }];

    keyboardShown = YES;
}

- (void)keyboardHidden:(NSNotification*)notification {

    NSNumber *rate = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey];

    // Remove/hide the accessory view so that next time the text field gets focus, if a hardware
    // keyboard is used, the accessory bar is not shown.
    //
    [UIView animateWithDuration:rate.floatValue animations:^{
        self.textField.inputAccessoryView.hidden = YES;
        self.answerTextField.inputAccessoryView.userInteractionEnabled = NO;
    }];

    keyboardShown = NO;
}

注意已修改为userInteractionEnabled添加更改,以便隐藏的accessoryView不会点击。

答案 1 :(得分:2)

IIRC,当软件键盘出现时,观看者不会调整自己的大小。我正在通过UIKeyboardDidShow通知触发的keyboardDidShow方法调整视图大小。因此,应该足以检测该方法中的硬件与软件键盘,然后您可以跳过表格调整大小并隐藏输入附件视图(或调整表格大小调整以适应输入附件视图,如果您希望保持可见)。

无论硬件键盘是否存在,要正确调整视图大小,我都会调整this answer中的代码:

- (void)keyboardDidShow:(NSNotification *)aNotification {
    CGRect keyboardBeginFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGRect keyboardEndFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    float keyboardHeight = ABS(keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y); // the keyboard will move by an amount equal to its height when it appears; ABS is needed for upside-down orientations

    // now you can resize your views based on keyboardHeight
    // that will be the height of the inputAccessoryView if a hardware keyboard is present
}

如果您想让inputAccessoryView可见,那就是您所需要的。为了隐藏它,我认为您需要设置一个实例变量,以便您可以在keyboardDidShow中访问它:

UIView *currentInputAccessoryView;

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    self.currentInputAccessoryView = textField.inputAccessoryView;
}

- (void)textViewDidBeginEditing:(UITextView *)textView {
    self.currentInputAccessoryView = textView.inputAccessoryView;
}

- (void)keyboardDidShow:(NSNotification *)aNotification {
    CGRect keyboardBeginFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGRect keyboardEndFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    float keyboardHeight = ABS(keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y); // the keyboard will move by an amount equal to its height when it appears; ABS is needed for upside-down orientations

    if (keyboardHeight == 44) {
        self.currentInputAccessoryView.hidden = YES;
        keyboardHeight = 0;
    }

    // now you can resize your views based on keyboardHeight
    // that will be 0 if a hardware keyboard is present
}

答案 2 :(得分:0)

我解决此问题的最后方法是简单地为UIKeyboardWillShowNotification ...

添加一个观察者
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification object:nil];

..并隐藏先前存储在实例变量中的inputAccessoryView

// Called when the UIKeyboardWillShowNotification is sent.
- (void)keyboardWillShow:(NSNotification*)notification
{
    NSLog(@"keyboardWillShow");

    // get the frame end user info key
    CGRect kbEndFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    // calculate the visible portion of the keyboard on the screen
    CGFloat height = [[UIScreen mainScreen] bounds].size.height - kbEndFrame.origin.y;

    // check if there is a input accessorry view (and no keyboard visible, e.g. hardware keyboard)
    if (self.activeTextField && height <= self.activeTextField.inputAccessoryView.frame.size.height) {

        NSLog(@"hardware keyboard");

        self.activeTextField.inputAccessoryView.hidden = YES;
    } else {

        NSLog(@"software keyboard");

        self.activeTextField.inputAccessoryView.hidden = NO;
    }
}

事实证明,问题是由我在其getter方法中动态创建自定义inputAccessoryView子类的UITextField引起的。每次调用getter时我无意中重新创建视图,而不是重复使用实例变量和惰性实例化。这导致我对视图的所有分配都被忽略,因为当访问文本字段并显示键盘时,显然getter方法将被称为多次,因此视图保持被覆盖< / strong>在我的任务之后。 通过将视图保存到实例变量来重用视图解决了此问题。