有没有办法检测iPad是否连接了外部(蓝牙或usb)键盘?
UIKeyboardWillShowNotification
本地通知。
您可以侦听更新:自iOS 9以后,这已不再正确,但您可以使用键盘尺寸来确定硬件或软件键盘是否涉及。有关详细信息,请参见如何可靠地检测iOS 9上是否连接了外部键盘?。
"GSEventHardwareKeyboardAttached"
(kGSEventHardwareKeyboardAvailabilityChangedNotification
) Darwin通知,但这是私有API,因此如果使用此API可能会导致您的应用被拒绝。要检查外部硬件是否存在,请使用私有函数GSEventIsHardwareKeyboardAttached()
。UIKeyboardImpl.isInHardwareKeyboardMode
属性,但这也是私有API。还有另外一个层次需要考虑。
幸运的是,事件中有足够的信息来确定键盘是否会被呈现,尽管这仍然有点复杂。
如果我们检查通知字典,我们会看到以下信息:
UIKeyboardFrameBeginUserInfoKey = NSRect: {{0, 1024}, {768, 308}}
UIKeyboardFrameEndUserInfoKey = NSRect: {{0, 980}, {768, 308}}
那是在竖屏模式下;如果我们将设备旋转为倒立的竖屏模式,我们会得到:
UIKeyboardFrameBeginUserInfoKey = NSRect: {{0, -308}, {768, 308}}
UIKeyboardFrameEndUserInfoKey = NSRect: {{0, -264}, {768, 308}}
同样在 LandscapeLeft 和 LandscapeRight 方向,我们得到了不同的起始和结束位置。
嗯...这些数字是什么意思?你可以看到键盘一开始是离屏幕外的,但它确实会移动一点。更糟糕的是,根据设备的方向,键盘的位置也不同。
不过,我们已经有足够的信息来弄清楚发生了什么:
在@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);
即使在UITextView实例上使用一个设置为CGRectZero的UIView实例的inputAccessoryView,也可以通过硬件键盘获得键盘通知。
这是我用来从UIKeyboardWillShowNotification
中的键盘userInfo获取高度的代码。适用于物理键盘和虚拟键盘。
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;
switch
语句会更加简洁。 - Rivera根据这个线程,我已经编写了两个静态方法,我可以轻松从键盘通知方法中调用它们,以便在键盘出现时正确地调整视图的大小(通常是UIScrollViews),无论类型(软件 vs 硬件):
+ (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;
}
[[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];
}
由于先前回答中的大多数方法已在iOS 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!
}
GameController
框架使用GCKeyboard
和GCKeyboardDidConnect
/GCKeyboardDidDisconnect
通知来跟踪硬件键盘。您可以像这样做:import GameController
class ViewController: UIViewController {
var isHardwareKeyboardConnected: Bool
init() {
isHardwareKeyboardConnected = GCKeyboard.coalesced != nil
super.init(nibName: nil, bundle: nil)
startObservingHardwareKeyboard()
}
func startObservingHardwareKeyboard() {
NotificationCenter.default.addObserver(self, selector: #selector(hardwareKeyboardDidConnect), name: .GCKeyboardDidConnect, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(hardwareKeyboardDidDisconnect), name: .GCKeyboardDidDisconnect, object: nil)
}
@objc func hardwareKeyboardDidConnect(_ notification: Notification) {
print("[Keyboard] Hardware keyboard did connect")
isHardwareKeyboardConnected = true
}
@objc func hardwareKeyboardDidDisconnect(_ notification: Notification) {
print("[Keyboard] Hardware keyboard did disconnect")
isHardwareKeyboardConnected = false
}
}
这不是直接检测外部键盘是否存在的答案,而是我正在执行此操作以检测在屏幕底部显示与键盘相关的视图所需的实际高度。
CGRect keyboardFrame = [[[notification userInfo] objectForKey:@"UIKeyboardFrameEndUserInfoKey"] CGRectValue];
CGFloat keyboardRelatedViewsHeight = self.view.window.frame.size.height - keyboardFrame.origin.y;