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