2011-08-02 127 views
22

我已經看到幾個類似的問題,但沒有解決我的具體需求。我希望能夠編寫一個通用的幫助器方法,該方法返回UIView的最大可用幀大小,同時考慮應用程序是否具有狀態欄,導航欄和/或選項卡欄的任意組合,因爲我發現自己正在執行此操作時間。以編程方式確定UIView的最大可用幀大小

方法的定義是作爲UIScreen的延伸:

+ (CGRect) maximumUsableFrame; 

獲取尺寸帶或不帶狀態欄可以從

[UIScreen mainScreen].applicationFrame

屬性來得到的,但我不能圖找出一種確定是否存在導航欄或標籤欄的方式。我想過在應用程序委託中維護一些全局標誌,但這看起來非常笨重,並且停止了代碼的泛型和可重用。我也考慮過傳遞一個UIView作爲參數,獲取視圖的窗口,然後是rootViewController,然後看看是否設置了導航控制器屬性。如果是,則檢查導航控制器是否隱藏。如果你問我,這一切都很笨重。

任何想法將不勝感激。

戴夫

編輯:萬一從迦勒的回答結合的想法,這是使用的其他任何人:

// Extension to UIViewController to return the maxiumum usable frame size for a view 
@implementation UIViewController (SCLibrary) 

- (CGRect) maximumUsableFrame { 

    static CGFloat const kNavigationBarPortraitHeight = 44; 
    static CGFloat const kNavigationBarLandscapeHeight = 34; 
    static CGFloat const kToolBarHeight = 49; 

    // Start with the screen size minus the status bar if present 
    CGRect maxFrame = [UIScreen mainScreen].applicationFrame; 

    // If the orientation is landscape left or landscape right then swap the width and height 
    if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { 
     CGFloat temp = maxFrame.size.height; 
     maxFrame.size.height = maxFrame.size.width; 
     maxFrame.size.width = temp; 
    } 

    // Take into account if there is a navigation bar present and visible (note that if the NavigationBar may 
    // not be visible at this stage in the view controller's lifecycle. If the NavigationBar is shown/hidden 
    // in the loadView then this provides an accurate result. If the NavigationBar is shown/hidden using the 
    // navigationController:willShowViewController: delegate method then this will not be accurate until the 
    // viewDidAppear method is called. 
    if (self.navigationController) { 
     if (self.navigationController.navigationBarHidden == NO) { 

      // Depending upon the orientation reduce the height accordingly 
      if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { 
       maxFrame.size.height -= kNavigationBarLandscapeHeight; 
      } 
      else { 
       maxFrame.size.height -= kNavigationBarPortraitHeight; 
      } 
     } 
    } 

    // Take into account if there is a toolbar present and visible 
    if (self.tabBarController) { 
     if (!self.tabBarController.view.hidden) maxFrame.size.height -= kToolBarHeight; 
    } 
    return maxFrame; 
} 
+1

如果導航欄和TabBar可見,你可以找到高這樣說:'self.navigationController.navigationBar.frame.size.height;'和'self.tabBarController.tabBar.frame.size.height'。爲什麼稱爲kToolBarHeight的tabbar高度變量?=) – Alexander

+0

根據你想如何使用它,至少在我的情況下,我也更新了navController的框架原點,所以我確切知道我可以在ViewController中放置視圖的位置。否則,你仍然可能在導航欄下結束。 –

回答

7

我想你把你的方法用錯了地方。 UIScreen知道屏幕,但它並不(也不應該)知道屏幕上的顯示內容。它是負責管理視圖的視圖控制器,所以這就是該方法所屬的地方。此外,由於最大幀取決於特定視圖控制器的配置,因此應該是實例方法而不是類方法。我想你應該添加一個類別的UIViewController與方法:

- (CGRect) maximumUsableFrame; 

它仍然是相當通用的,適用於所有視圖控制器,但在同一時間訪問查看像navigationControllertabBarController控制器屬性。

+1

感謝指針的所有好東西,並使很多意義。將寫入擴展名,並讓你知道我如何繼續。 –

+2

已經向UIViewController添加了一個類別,並編輯了我的原始問題以包含代碼,並會感激您的想法。乾杯戴夫。 –

9

使用applicationFrame。 [[UIScreen mainScreen] applicationFrame]

這是我如何使用它在我的截圖中裁剪東西。

這是一些示例代碼。

-(UIImage*) crop20PointsifStatusBarShowsUp 
{ 
    CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame]; //Look at this 
    float sizeOfStatusBarVar= applicationFrame.origin.y; 
    if ([BGMDApplicationsPointers statusBarShowUp]) 
    { 
     CGRect newSize = CGRectMake(0, sizeOfStatusBarVar, self.size.width, self.size.height-sizeOfStatusBarVar); 
     UIImage * newImage = [self cropUIImageWithCGRect:newSize]; 
     return newImage; 
    } 
    else{ 
     return [self copy]; 
    } 
} 
+0

不知道爲什麼這不是最好的答案。 – Isak

0

爲了得到這個工作必須使用應用範圍和方向開關弄清楚從哪個方面看狀態欄應該被刪除。這是最初發布的代碼的複製和調整。我做了一個快速的應用程序,通過將navbar/tabbar/none與狀態欄組合在一起運行該算法,並在所有情況下都能正常工作。

- (CGRect) maxFrame 
{ 
    // Start with the screen size minus the status bar if present 
    CGRect maxFrame = [UIScreen mainScreen].applicationFrame; 

    // the glass screen size 
    CGRect maxBounds = [UIScreen mainScreen].bounds; 


NSLog(@"MaxFrame for %d: (%f, %f, %f, %f)", self.interfaceOrientation, maxFrame.origin.x, maxFrame.origin.y, maxFrame.size.width, maxFrame.size.height); 
NSLog(@"MaxBounds for %d: (%f, %f, %f, %f)", self.interfaceOrientation, maxBounds.origin.x, maxBounds.origin.y, maxBounds.size.width, maxBounds.size.height); 


    // figure out the offset of the status bar 
    CGFloat statusBarOffset; 
    switch (self.interfaceOrientation) { 
     case UIInterfaceOrientationPortrait: 
      statusBarOffset = maxFrame.origin.y; 
     break; 
     case UIInterfaceOrientationPortraitUpsideDown: 
      statusBarOffset = maxBounds.size.height - maxFrame.size.height; 
     break; 
     case UIInterfaceOrientationLandscapeRight: 
     case UIInterfaceOrientationLandscapeLeft: 
      statusBarOffset = maxBounds.size.width - maxFrame.size.width; 
     break; 
    } 

    // If the orientation is landscape left or landscape right then swap the width and height 
    if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { 
     CGFloat temp = maxBounds.size.height; 
     maxBounds.size.height = maxBounds.size.width; 
     maxBounds.size.width = temp; 
    } 

    // apply status bar to the top of the view 
    maxBounds.origin.y = statusBarOffset; 
    maxBounds.size.height -= statusBarOffset; 

    // Take into account if there is a navigation bar present and visible (note that if the NavigationBar may 
    // not be visible at this stage in the view controller's lifecycle. If the NavigationBar is shown/hidden 
    // in the loadView then this provides an accurate result. If the NavigationBar is shown/hidden using the 
    // navigationController:willShowViewController: delegate method then this will not be accurate until the 
    // viewDidAppear method is called) 
    if (self.navigationController && !self.navigationController.navigationBarHidden) { 
     NSLog(@"has nav bar"); 
     maxBounds.size.height -= self.navigationController.navigationBar.frame.size.height; 
     maxBounds.origin.y += self.navigationController.navigationBar.frame.size.height; 
    } 

    // Take into account if there is a toolbar present and visible 
    if (self.tabBarController && !self.tabBarController.view.hidden) { 
     maxBounds.size.height -= self.tabBarController.tabBar.frame.size.height; 
     NSLog(@"has tab bar"); 
    } 

NSLog(@"result for %d: (%f, %f, %f, %f)", self.interfaceOrientation, maxBounds.origin.x, maxBounds.origin.y, maxBounds.size.width, maxBounds.size.height); 
    return maxBounds; 
} 
+0

必須評論maxBounds.origin.y = statusBarOffset;和maxBounds.origin.y + = self.navigationController.navigationBar.frame.size.height;在一個不同的應用程序這是用於。 –

相關問題