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