4

我有一个视图控制器用UITextView显示一个视图,我想在键盘出现时调整视图的大小,以便UITextView不被键盘覆盖。我几乎在所有情况下都能正常工作。据我所知,只有当视图控制器在ModalPresentationStyleFormSheet中呈现,并且仅在LandscapeRight方向呈现时,我仍然在iPad上看到一些奇怪的现象。如何找到未被键盘覆盖的部分视图(UIModalPresenationStyleFormSheet)?

我的视图控制器的-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得到的原点比它应该低很多。什么可能导致这个?

感谢您的帮助!

回答

2

这里是我如何处理键盘与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); 
} 
+1

这对我很好。我发现的唯一的错误是对于UIInterfaceOrientationLandscapeLeft或UIInterfaceOrientationLandscapeRight,您仍然应该使用'keyboardSize.height',而不是'keyboardSize.width'。 (在iOS 7.0 iPad模拟器上测试) –

+0

出于某种原因,设置contentInsets看起来没有任何作用。你有一些示例代码显示这个片段的工作? – fatuhoku

+0

@RizwanSattar我也需要使用windowBounds.size.height,而不是windowBounds.size.width –

1

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

在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 
} 
4

威尔的答案是正确的想法,但我不得不调整它颇有几分得到它的权利

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) 
    } 
}