iOS开发 -- IOS7界面兼容,从4.3到7.0兼容的NavigationBar ,IOS7 NavigationBar 适配

最近项目有个棘手的问题--适配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

 


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值