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

时间: 2024-10-10 21:57:20

iOS7 界面适配-NavigationBar StateBar的相关文章

Unity3d UGUI 界面适配 实例解析 三种适配方式

之前做游戏都是用公司自己的引擎,对于界面的适配分Android和IOS两种系统处理. 对于IOS设备,由于数量有限,只要做到 960x640  1024x769 1136x640 (当时还没有iphone6呢) 三种适配即可,所以我们对这三种屏幕做了三种不同的界面配置文件. 对于安卓设备,屏幕分辨率实在太多种,所以统一设置为1136x640的缩放比例了. 现在使用Unity制作游戏,虽然仍然可以使用原来的这一套方案,但是却显得没有这个必要了. Unity4.6新版UGUI,提供了三种基本的界面适

iOS:界面适配--iPhone不同机型适配 6/6plus

iOS:界面适配--iPhone不同机型适配 6/6plus        机型变化 坐标:表示屏幕物理尺寸大小,坐标变大了,表示机器屏幕尺寸变大了: 像素:表示屏幕图片的大小,跟坐标之间有个对应关系,比如1:1或1:2等: ppi:代表屏幕物理大小到图片大小的比例值,如果ppi不变,则坐标和像素的比例不会变: iPhone 4以前 iPhone.iPhone3/3G机型未采用retina,坐标是320 x 480,屏幕像素320 x 480 ,他们一一对应,1:1关系.即一个坐标对应1个像素.

IOS界面适配二: Auto Layout的使用(上)

上一篇讲了IOS中基础的距离单位,链接为 IOS界面适配一: Pt与Px的关系 ,使用距离单位可以定义我们程序中View的大小,但是,仅仅使用Pt定义大小是远远不够的. 比如,我们想让一个button距离手机左边界为20pt,右边界为20pt,距上为30pt,高度自身为20pt,如果在iphone5中(为320pt*568pt),我们要在代码中这么定义 以下代码写在ViewController中的viewDidLoad方法中: UIButton * button = [[UIButton all

Ios 6和ios7的适配

Ios 6和ios7的适配 1.普通的 ViewController:让view的显示从状态栏下面开始,只需在viewDidLayoutSubviews调整 view的bounds CGRect bounds = self.view.bounds; bounds.origin.y =  - [self.topLayoutGuide length]; self.view.bounds = bounds; 2.ScrollView 类型的 在viewDidLoad 里面加: if ([[UIDevi

iOS:界面适配(三)--iPhone不同机型或设备不同尺寸适配(屏幕适配)和系统适配

对于不同苹果设备,各个参数查看<iOS:机型参数.sdk.xcode各版本>.        机型变化 坐标:表示屏幕物理尺寸大小,坐标变大了,表示机器屏幕尺寸变大了: 像素:表示屏幕图片的大小,跟坐标之间有个对应关系,比如1:1或1:2等: ppi:代表屏幕物理大小到图片大小的比例值,如果ppi不变,则坐标和像素的比例不会变: iPhone 4以前 iPhone.iPhone3/3G机型未采用retina,坐标是320 x 480,屏幕像素320 x 480 ,他们一一对应,1:1关系.即一

IOS7 TableView适配

ios7下的app都是全屏的,意思就是所有控制器的view默认都是从屏幕的(0,0)开始. 为了达到全屏效果的app,官方为UIviewController增加了几个属性: 1 @property(nonatomic,assign) UIRectEdge edgesForExtendedLayout NS_AVAILABLE_IOS(7_0); // Defaults to UIRectEdgeAll 2 @property(nonatomic,assign) BOOL extendedLayo

iOS6与iOS7屏幕适配技巧

一.没有包装任何 导航控制器 或者UITabBarController 1.控制器的view是UIScrollView/UITableView/UICollectionView时(控制器是UITableViewController的时候) - (void)viewDidLoad { [super viewDidLoad]; // #ifdef __IPHONE_7_0是判断是否运行在Xcode5环境下,如果在Xcode5环境下才有下面的代码 #ifdef __IPHONE_7_0 if ([[U

移动端界面适配

本文引自:http://www.cnblogs.com/xianyulaodi/p/5533201.html 摘要:在进行移动端界面的书写的时候,如果把宽度高度或者字体大小全部写死的话,那么在所有手机上看到的大小都一样,存在的问题就是同样大小的字体,或者一个盒子模型, 在大屏幕手机上看起来会有点偏小.比如iphone6PLUS.如果是做成适配的话,就很好的解决了这个问题,大屏幕显示的内容大一点,小屏幕显示的小一点. 所以今天做一个移动端页面适配的小小总结 适配的要求 1.在不同分辨率的手机上,页

安卓基础之界面适配问题——FOX出品

今天呢,想要讲解一下关于安卓手机界面的适配问题该如何去解决和避免.现在市面上面的安卓机各种各样的界面,但是界面还是有大部分的主流机型.现在很多的菜鸟们其实没有感受到真正的如何去适配界面,和如何去解决这个问题.那么今天我就大概写一下关于这一方面的思路.其实呢,要完全解决适配问题其实很难的.不仅仅我们要对一个这些布局的理解.比如Relayout这个布局,linelayout这个布局这些布局进行一个大概的了解.这是必须的.比如对于Relayout这个布局而言是一个使用十分频繁的一个布局问题.但是这个布