iOS7 界面适配-NavigationBar StateBar

 

转 blog.csdn.net/ibcker/article/details/12115437

最近项目有个棘手的问题--适配IOS7....

由于IOS7把整个内容区都上移了20,所以很多不是全屏的应用都不能很好的兼容,换用苹果文档的一句话就是说:如果你们原来的app就是全屏模式运行的,那你们几乎不用改,如果不是,那·····

 

改之前很有必要去阅读下苹果官方的《ios7过渡指南》http://t.cn/zRv5lQT  ,当然,也有人翻译了一份··如果那什么可以看中文的·· http://t.cn/zHDbDCz (吐槽下“实现方法是在Info.plist中加入键UIViewControllerBasedStatusBarAppearance,并设置值为YES。”这句话好像翻译反了··)

来说说问题,由于主要问题界面给默认全屏了···也就是说原来statusbar的20像素没了,所以如果想比较快速的适配ios7,比较好的做法是:


step 1 写个UIViewController的Category让UIViewController默认的wantsFullScreenLayout返回YES,同时edgesForExtendedLayout默认返回All,目的是让所有版本都统一全屏


.h代码如下

 

    #import <UIKit/UIKit.h>  
      
    #ifndef __IPHONE_7_0  
    typedef NS_OPTIONS(NSUInteger, UIRectEdge) {  
        UIRectEdgeNone   = 0,  
        UIRectEdgeTop    = 1 << 0,  
        UIRectEdgeLeft   = 1 << 1,  
        UIRectEdgeBottom = 1 << 2,  
        UIRectEdgeRight  = 1 << 3,  
        UIRectEdgeAll    = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight  
    };  
    #endif  
      
    @interface UIViewController (UIRectEdge)  
      
    //#ifndef __IPHONE_7_0  
    - (BOOL)automaticallyAdjustsScrollViewInsets;  
    - (void)setAutomaticallyAdjustsScrollViewInsets:(BOOL)b;  
    - (UIRectEdge)edgesForExtendedLayout;  
    - (void)setEdgesForExtendedLayout:(UIRectEdge)rect;  
    //#endif  
    @end  
 

.m

 
    #import "UIViewController+UIRectEdge.h"  
      
    #import <objc/runtime.h>  
      
    @implementation UIViewController (UIRectEdge)  
      
    static const charchar *kWantsFullScreenLayoutKey;  
      
    - (BOOL)wantsFullScreenLayout  
    {  
        id v=objc_getAssociatedObject(self,&kWantsFullScreenLayoutKey);  
        if (v!=nil) {  
            return [v boolValue];  
        }else{  
            return YES;  
        }  
    }  
      
    - (void)setWantsFullScreenLayout:(BOOL)b  
    {  
        objc_setAssociatedObject(self, &kWantsFullScreenLayoutKey, @(b), OBJC_ASSOCIATION_ASSIGN);  
    }  
      
    static const charchar *kAutomaticallyAdjustsScrollViewInsetsKey;  
      
    - (BOOL)automaticallyAdjustsScrollViewInsets  
    {  
        id v=objc_getAssociatedObject(self,&kAutomaticallyAdjustsScrollViewInsetsKey);  
        if (v!=nil) {  
            return [v boolValue];  
        }else{  
            return NO;  
        }  
    }  
      
    - (void)setAutomaticallyAdjustsScrollViewInsets:(BOOL)b  
    {  
        objc_setAssociatedObject(self, &kAutomaticallyAdjustsScrollViewInsetsKey, @(b), OBJC_ASSOCIATION_ASSIGN);  
    }  
      
      
    static const charchar *kEdgesForExtendedLayoutKey;  
      
    - (UIRectEdge)edgesForExtendedLayout  
    {  
        id v=objc_getAssociatedObject(self,&kEdgesForExtendedLayoutKey);  
        if (v!=nil) {  
            return [v integerValue];  
        }else{  
            return UIRectEdgeAll;  
        }  
    }  
      
    - (void)setEdgesForExtendedLayout:(UIRectEdge)rect  
    {  
        objc_setAssociatedObject(self, &kEdgesForExtendedLayoutKey, @(rect), OBJC_ASSOCIATION_ASSIGN);  
    }  
      
    @end  



step 2 然后写个UIApplication的category让5,6上状态栏底色消失.

照例直接贴代码

.h

 
    #import <UIKit/UIKit.h>  
      
    @interface UIApplication (UI7)  
    + (void)inject;  
    @end  


.m

 
    #import "UIApplication+UI7.h"  
    #import <objc/runtime.h>  
    #import <QuartzCore/QuartzCore.h>  
      
    #define _IOS_VERSION_UI7 ([[[UIDevice currentDevice] systemVersion] floatValue])  
      
    #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_4_3  
    #error UI7NavigationBar doesn't support Deployement Target version < 4.3  
    #endif  
      
    @implementation UIApplication (UI7)  
      
    + (void)inject  
    {  
        Method originMethod=class_getInstanceMethod(self, @selector(setStatusBarStyle:));  
        Method newMethod=class_getInstanceMethod(self, @selector(__setStatusBarStyle:));  
          
        method_exchangeImplementations(originMethod, newMethod);  
          
        originMethod=class_getInstanceMethod(self, @selector(setStatusBarStyle:animated:));  
        newMethod=class_getInstanceMethod(self, @selector(__setStatusBarStyle:animated:));  
          
        method_exchangeImplementations(originMethod, newMethod);  
    }  
      
    - (void)__setStatusBarStyle:(UIStatusBarStyle)style  
    {  
        [self __setStatusBarStyle:style];  
        if (style==UIStatusBarStyleBlackTranslucent) {  
            [self hiddenStatusBarBackground:YES];  
        }  
    }  
      
    -(void)__setStatusBarStyle:(UIStatusBarStyle)style animated:(BOOL)animated  
    {  
        [self __setStatusBarStyle:style animated:animated];  
          
        if (style==UIStatusBarStyleBlackTranslucent) {  
            if (animated) {  
                [self performSelector:@selector(hiddenStatusBarBackground:) withObject:@(YES) afterDelay:0.6];  
            }else{  
                [self hiddenStatusBarBackground:YES];  
            }  
        }  
    }  
      
    - (void)hiddenStatusBarBackground:(BOOL)hidden  
    {  
        if(_IOS_VERSION_UI7<7){  
            BOOL isStatusBarHidden=[[UIApplication sharedApplication] isStatusBarHidden];  
            if (isStatusBarHidden) {  
                [[UIApplication sharedApplication] setStatusBarHidden:NO];  
            }  
            UIView *statusbar=[[UIApplication sharedApplication] valueForKey:@"_statusBar"];  
            NSArray *vs=[statusbar subviews];  
            for (UIView *v in vs) {  
                if ([v isKindOfClass:NSClassFromString(@"UIStatusBarBackgroundView")]) {  
                    statusbar=v;  
                    break;  
                }  
            }  
            if (isStatusBarHidden) {  
                [[UIApplication sharedApplication] setStatusBarHidden:YES];  
            }  
            if (hidden) {  
                [statusbar setHidden:YES];  
            }else{  
                [statusbar setHidden:NO];  
            }  
        }  
    }  
      
    @end  

 


step 3实现一个UINavigationBar的子类,让自定义效果更加简单

.h

 
#import <UIKit/UIKit.h>  
  
typedef NS_ENUM(NSUInteger, UI7NavBarSytle)  
{  
    UI7NavBarSytleLight, //0.4 alpha  
    UI7NavBarSytleDark, //0.8 alpha  
    UI7NavBarSytleBlack, //1.0  
};  
  
@interface TTNavigationController : UINavigationController  
  
- (void)setNavBarBgWithImage:(UIImage *)image;  
- (void)setNavBarBgWithColor:(UIColor *)cl;  
- (void)setNavBarStyle:(UI7NavBarSytle)style;  
  
@end 


.m

#import "TTNavigationController.h"  
#import "UIApplication+UI7.h"  
  
@interface TTNavigationController ()  
@property (nonatomic,strong)UIImageView *navColorOverly;  
@end  
  
@implementation TTNavigationController  
  
  
- (void)viewDidLoad  
{  
    [super viewDidLoad];  
      
    self.navigationBar.opaque = NO;  
    if (kCFCoreFoundationVersionNumber>=kCFCoreFoundationVersionNumber_iOS_5_0) {  
        NSArray *vs=[self.navigationBar subviews];  
        Class clazz;  
        if (kCFCoreFoundationVersionNumber>=kCFCoreFoundationVersionNumber_iOS_6_0) {  
            clazz=NSClassFromString(@"_UINavigationBarBackground");  
        }else{  
            clazz=NSClassFromString(@"UINavigationBarBackground");  
        }  
        for (UIView *v in vs) {  
            if ([v isKindOfClass:clazz]) {  
                v.hidden=YES;  
                break;  
            }  
        }  
    }  
    [self setNavBarStyle:UI7NavBarSytleDark];  
    [self.navigationBar insertSubview:_navColorOverly atIndex:0];  
}  
  
  
  
- (UIImageView *)navColorOverly  
{  
    if (!_navColorOverly) {  
        if (!_navColorOverly) {  
            _navColorOverly=[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.navigationBar.frame.size.width, self.navigationBar.frame.size.height+20)];  
            _navColorOverly.frame=CGRectMake(0, -20, self.navigationBar.frame.size.width, 64);  
        }  
    }  
    return _navColorOverly;  
}  
  
- (void)setNavBarStyle:(UI7NavBarSytle)style  
{  
    switch (style) {  
        case UI7NavBarSytleLight:  
            [self setNavBarBgWithColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.4]];  
            break;  
        case UI7NavBarSytleBlack:  
            [self setNavBarBgWithColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:1]];  
            break;  
        default: //UI7NavBarSytleDark:  
            [self setNavBarBgWithColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.8]];  
            break;  
    }  
}  
  
- (void)setNavBarBgWithColor:(UIColor *)cl  
{  
    UIGraphicsBeginImageContext(CGSizeMake(1, 1));  
    [cl set];  
    UIRectFill(CGRectMake(0, 0, 1, 1));  
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();  
    UIGraphicsEndImageContext();  
    self.navColorOverly.image=[image stretchableImageWithLeftCapWidth:1 topCapHeight:1];  
}  
  
- (void)setNavBarBgWithImage:(UIImage *)image  
{  
    self.navColorOverly.image=image;  
}  
  
@end  
@implementation UINavigationBar (CustomImage)  
- (void)drawRect:(CGRect)rect {}  
@end 

step 4接着是刚才提到的,在info.plist里加入UIViewControllerBasedStatusBarAppearance,设为NO



step 5接着就写个Demo试试效果吧。

记得appdelegate的application:didFinishLaunchingWithOptions:里记得调用[UIApplicationinject];作用就是注入状态栏,让其底色透明



简单看下效果(iOS 5,6,7):

 

 

https://github.com/iBcker/UI7NavigationBar

原文地址:https://www.cnblogs.com/allanliu/p/4532686.html