2011-08-02 82 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;在一个不同的应用程序这是用于。 –

相关问题