最近项目有个棘手的问题--适配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 char *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 char *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 char *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):
代码去github取吧,如果写不好不要吐槽··哈哈··
https://github.com/iBcker/UI7NavigationBar