如何找到键盘未覆盖的视图部分(UIModalPresenationStyleFormSheet)?

我有一个视图控制器显示带有UITextView的视图,我想在键盘出现时调整视图大小,以便键盘不会覆盖UITextView。 我几乎在所有情况下都能正常工作。 我仍然在iPad上看到一些奇怪的东西,只有当视图控制器出现在ModalPresentationStyleFormSheet中时,并且只有在LandscapeRight方向上,据我所知。

我的视图控制器的相关部分-keyboardWillShow:

// We'll store my frame above the keyboard in availableFrame CGRect availableFrame = self.view.frame; // Find the keyboard size NSDictionary *userInfo = [notification userInfo]; NSValue keyboardFrameScreenValue = userInfo[UIKeyboardFrameBeginUserInfoKey]; CGRect keyboardFrameScreen = [keyboardFrameScreenValue CGRectValue]; CGRect keyboardFrame = [self.view convertRect:keyboardFrameScreen fromView:nil]; CGSize keyboardSize = keyboardFrame.size; // Figure out how much of my frame is covered by the keyboard CGRect screenBounds = [self.view convertRect:[UIScreen mainScreen].bounds fromView:nil]; CGRect myBoundsScreen = [self.view boundsInWindow]; // See below CGFloat myBottom = myBoundsScreen.origin.y + myBoundsScreen.size.height; CGFloat keyboardTop = screenBounds.size.height - keyboardSize.height; CGFloat lostHeight = myBottom - keyboardTop; availableFrame.size.height -= lostHeight; 

– [UIView boundsInWindow]:

 - (CGRect)boundsInWindow { UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; CGRect bounds = [self convertRect:self.bounds toView:self.window]; if (UIInterfaceOrientationIsLandscape(orientation)) { // Swap origin CGFloat x = bounds.origin.y; bounds.origin.y = bounds.origin.x; bounds.origin.x = x; // Swap size CGFloat width = bounds.size.height; bounds.size.height = bounds.size.width; bounds.size.width = width; } return bounds; } 

大部分时间都可以使用。 当我的应用程序处于用户界面方向LandscapeRight时,我从-boundsInWindow得到的原点比它应该低得多。 可能是什么导致了这个?

谢谢你的帮助!

威尔的答案是正确的想法,但我不得不调整它以使其正确

 extension UIView { func heightCoveredByKeyboardOfSize(keyboardSize: CGSize) -> CGFloat { let frameInWindow = convertRect(bounds, toView: nil) guard let windowBounds = window?.bounds else { return 0 } let keyboardTop = windowBounds.size.height - keyboardSize.height let viewBottom = frameInWindow.origin.y + frameInWindow.size.height return max(0, viewBottom - keyboardTop) } } 

以下是我使用iPad表单处理键盘的方法:

 - (void)UIKeyboardDidShowNotification:(NSNotification*)aNotification { NSDictionary *userInfo = [aNotification userInfo]; CGSize keyboardSize = [userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, [self.view heightCoveredByKeyboardOfSize:keyboardSize], 0.0); [UIView animateWithDuration:.25f animations:^{ self.scrollView.contentInset = contentInsets; self.scrollView.scrollIndicatorInsets = contentInsets; }]; } 

UIView上的类别:

 - (CGFloat)heightCoveredByKeyboardOfSize:(CGSize)keyboardSize { UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; CGRect frameInWindow = [self convertRect:self.bounds toView:nil]; CGRect windowBounds = self.window.bounds; CGFloat keyboardTop; CGFloat heightCoveredByKeyboard; //Determine height of the view covered by the keyboard relative to current rotation switch (orientation) { case UIInterfaceOrientationLandscapeLeft: keyboardTop = windowBounds.size.width - keyboardSize.width; heightCoveredByKeyboard = CGRectGetMaxX(frameInWindow) - keyboardTop; break; case UIInterfaceOrientationLandscapeRight: keyboardTop = windowBounds.size.width - keyboardSize.width; heightCoveredByKeyboard = windowBounds.size.width - frameInWindow.origin.x - keyboardTop; break; case UIInterfaceOrientationPortraitUpsideDown: keyboardTop = windowBounds.size.height - keyboardSize.height; heightCoveredByKeyboard = windowBounds.size.height - frameInWindow.origin.y - keyboardTop; break; default: keyboardTop = windowBounds.size.height - keyboardSize.height; heightCoveredByKeyboard = CGRectGetMaxY(frameInWindow) - keyboardTop; break; } return MAX(0.0f,heightCoveredByKeyboard); } 

我想我找到了一个相当不错的答案。 您可以使用UIView上的convertRect:fromView:方法转换坐标系。

在swift代码中,UIKeyboardNotification调用的选择器如下所示:

 func keyboardWasShown(notification: NSNotification) { let info = notification.userInfo! let keyboardRect = (info[UIKeyboardFrameEndUserInfoKey]! as NSValue).CGRectValue() // Convert the keyboard rect into the view controller's coordinate system // The fromView: nil means keyboardRect is in the main window's coordinate system let newSize = self.view.convertRect(keyboardRect, fromView: nil) // And then this is the part that gets covered! let keyboardCoveredHeight = self.view.bounds.height - newSize.origin.y // Note: you may have to use self.navigationController!.view.bounds.height if // you've wrapped your view in a navigation controller because this will // include the height of the navigation bar // You can then adjust the content inset of the text view accordingly textView.scrollIndicatorInsets.bottom = keyboardCoveredHeight textView.contentInset.bottom = keyboardCoveredHeight }