以编程方式确定UIView的最大可用帧大小

Mag*_*ave 22 cocoa-touch uiviewcontroller uiview ios

我已经看到了几个类似的问题,但没有一个能满足我的特殊需求.我希望能够编写一个通用的辅助方法,它返回UIView的最大可用帧大小,考虑到应用程序是否具有状态栏,导航栏和/或标签栏的任意组合,因为我发现自己这样做了时间.

方法定义将作为UIScreen的扩展:

+ (CGRect) maximumUsableFrame;
Run Code Online (Sandbox Code Playgroud)

可以从中获取带或不带状态栏的大小

[UIScreen mainScreen].applicationFrame

属性,但我无法找出一种方法来确定是否存在导航栏或标签栏.我已经考虑过在我的app委托中维护一些全局标志,但这看起来非常笨重,并且停止了代码的通用性和可重用性.我还考虑将UIView作为参数传递,获取视图的窗口,然后是rootViewController,然后查看是否设置了导航控制器属性.如果是,则检查导航控制器是否隐藏.如果你问我,一切都很笨重.

任何想法将不胜感激.

戴夫

编辑:结合Caleb答案中的想法,以防其他人使用:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

use*_*951 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];
    }
}
Run Code Online (Sandbox Code Playgroud)


Cal*_*leb 7

我想你把你的方法放在了错误的地方.UIScreen知道屏幕,但它没有(也不应该)知道发生了什么事情显示屏幕上.视图控制器负责管理视图,因此该方法属于该视图.此外,由于最大帧取决于特定视图控制器的配置,因此这应该是实例方法而不是类方法.我认为你应该使用以下方法向UIViewController添加一个类别:

- (CGRect) maximumUsableFrame;
Run Code Online (Sandbox Code Playgroud)

它仍然相当通用,可供所有视图控制器使用,但同时可以访问视图控制器属性,如navigationControllertabBarController.

  • 已经在UIViewController中添加了一个类别,并编辑了我的原始问题以包含代码,并会感谢您的想法.干杯戴夫. (2认同)