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

类似于这个问题: iPad:检测外部键盘 ,我正在开发一个iPad应用程序,使用文本字段与自定义inputAccessoryView提供虚拟键盘的附加function。

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

我发现了几个解决scheme来检测是否连接了硬件键盘,但是他们都收到UIKeyboardDidShowNotification 检查状态,此时inputAccessoryView已经可见(例如, 如何检测iPad上是否有外部键盘? 。

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

这里提供的接受解决scheme如何检测iPad上是否有外接键盘? 对我来说是没有select的,因为他们使用的私人API可能会导致我的应用程序被拒绝。

这只是@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不会吃水龙头。

IIRC,当软件键盘出现时,视图不会自行resize。 我在通过UIKeyboardDidShow通知触发的keyboardDidShow方法中调整视图的大小。 因此,在该方法中检测硬件和软件键盘应该足够了,然后您可以跳过表格大小调整并隐藏input附件视图(或者调整表格大小以适应input附件视图,如果您希望保留该视图)。

不pipe硬件键盘是否存在,要正确调整视图的大小,我调整了这个答案的代码:

 - (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可见,那就是你所需要的。 为了也隐藏,我想你将需要设置一个实例variables,以便您可以在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 } 

我最终解决这个问题的方法是简单地为UIKeyboardWillShowNotification添加一个观察者…

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

..并隐藏以前存储在实例variables中的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, eg 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; } } 

事实certificate,这个问题是由我在其getter方法中dynamic地创build了我自定义的UITextField子类的inputAccessoryView引起的。 我无意中重新创build了每次调用getter的视图,而不是重复使用一个实例variables和懒惰的实例化。 这导致我所有的视图都被忽略,因为当访问文本字段时显然getter方法会被多次调用,并且显示键盘,因此视图在我的赋值之后被覆盖 。 通过将视图保存到实例variables来重新使用该视图可以解决此问题。