原文网址:http://blog.csdn.net/joonsheng/article/details/41362499

说到自定义UINavigetionController的返回按钮,iOS7以后,多了一个“<” 这样的返回图标,而目前主流的应用,都是只保留了“<”,而去掉了文字,那么怎么样自定义一个自己的“<"按钮,或者用系统的“<”,但不要文字呢?

1.设置中的返回按钮(带文字)

2.音乐中播放时(不带文字)

1、直接上答案

  1. //下面这两句是让系统的返回按钮的文字为空,从而达到隐藏文字的作用
  2. UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil];
  3. self.navigationItem.backBarButtonItem = backItem;
  4. //这句就是push了,所以在push前加上这样一句,就保留了系统的自带的“<",并且文字为空
  5. [self.navigationController pushViewController:registerVC animated:YES];

注:本文代码,如果没有说明,都是从A导航视图push到B导航视图时,在A导航视图里设置的代码。

看图:

2、带着问题看答案:

1、上面的方法,只是利用了系统的自带"<", 有人可能就问,那如果我想自定义图标呢?

  1. //下面两行就是自定义,替换系统的“<"图标
  2. 【1】    [self.navigationController.navigationBar setBackIndicatorImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]];
  3. [self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]];
  4. UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil];
  5. self.navigationItem.backBarButtonItem = backItem;

这个方法,如果只是适配iOS 7以上,那么,是目前比较好的解决方案了。

特点:

1.实现了自定义图标,可以没有文字,

2.保存了iOS 7以上系统的pop手势返回。

如果要适配iOS 6,那么就要判断系统版本,如果大于iOS 7,就用上面的代码,如果低于iOS 7.0,就用另外的代码(下面在介绍)

效果如下图:

backItem;

2、那么,我们在A视图设置的代码,系统是如何实现从A视图push到B视图后,显示在B视图的?

看图:

显示原理【2】:

1、如果B视图有一个自定义的左侧按钮(leftBarButtonItem),则会显示这个自定义按钮;

2、如果B没有自定义按钮,但是A视图的backBarButtonItem属性有自定义项,则显示这个自定义项;

3、如果前2条都没有,则默认显示一个后退按钮,后退按钮的标题是A视图的标题。

3、如果理解了第2点,那么怎样自定义代码,才能适配iOS 6和iOS 7以上呢?

自定义要求:

1.自定义图标,文字可要可不要。

2.对于iOS 7以上,保留pop手势.

分析:如果在A视图自定义了返回按钮,又要适配iOS6 ,但由于iOS6 下没有手势返回,所以只能点击左上角返回,怎么处理?

直接上答案:

方案一【3】:

在A视图中:

  1. if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))  //如果系统版本在iOS 7.0以上,执行
  2. {
  3. [self.navigationController.navigationBar setBackIndicatorImage:[UIImage imageNamed:@"name="navibar_back_btn_bg_normal.png"]];
  4. [self.navigationController.navigationBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]];
  5. UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil];
  6. self.navigationItem.backBarButtonItem = backItem;
  7. }


在B视图中:

  1. if (SYSTEM_VERSION_LESS_THAN(@"7.0"))  //如果系统版本在iOS 7.0以下(不包括7.0),执行
  2. {
  3. //导航条返回按钮
  4. UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
  5. [button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png]forState:UIControlStateNormal];
  6. [button setFrame:CGRectMake(0,0,30,30)">];
  7. [button addTarget:self action:@selector(jumpBack:) forControlEvents:UIControlEventTouchUpInside];
  8. UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  9. self.navigationItem.leftBarButtonItem = barButtonItem;
  10. }


  1. #pragma mark - 跳转回去
  2. - (void)jumpBack:(id)sender{
  3. [self.navigationController popViewControllerAnimated:YES];
  4. }

方案二:

//在A视图中:

  1. //开启iOS7的滑动返回效果
  2. if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
  3. self.navigationController.interactivePopGestureRecognizer.delegate = nil;
  4. }
  5. [self.navigationController pushViewController:registerVC animated:YES];

//在B视图中(ViewDidLoad):

  1. //导航条返回按钮
  2. UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
  3. [button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png]forState:UIControlStateNormal];
  4. [button setFrame:CGRectMake(0,0,30,30)];
  5. [button addTarget:self action:@selector(jumpBack:) forControlEvents:UIControlEventTouchUpInside];
  6. UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  7. self.navigationItem.leftBarButtonItem = barButtonItem;



  1. #pragma mark - 跳转回去
  2. - (void)jumpBack:(id)sender{
  3. [self.navigationController popViewControllerAnimated:YES];
  4. }

 

这个方案,不用适配iOS 6和iOS 7,与方案一区别是,箭头比较靠右边,为什么?说到这个,我下一篇文章在会针对Navigation层次结构在说吧。

 
如图:
 
 

方案三:

在B视图中:
  1. - (void)viewWillAppear:(BOOL)animated
  2. {
  3. // 注意,这个<span style="font-family: Arial, Helvetica, sans-serif;">interactivePopGestureRecognizer</span><span style="font-family: Arial, Helvetica, sans-serif;">属性是iOS 7才有的</span>
  4. self.navigationController.interactivePopGestureRecognizer.delegate = self;
  5. }
 
  1. //导航条返回按钮
  2. UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
  3. [button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"]
  4. forState:UIControlStateNormal];
  5. [button setFrame:CGRectMake(0,0,30,30)];
  6. [button addTarget:self action:@selector(jumpBack:) forControlEvents:UIControlEventTouchUpInside];
  7. UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  8. self.navigationItem.leftBarButtonItem = barButtonItem;
  9. #pragma mark - 跳转回去
  10. - (void)jumpBack:(id)sender{
  11. [self.navigationController popViewControllerAnimated:YES];
  12. }

3、自定义几点说明

1.返回文字可以自定义为照片

  1. UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed: @"navibar_back_btn_bg_normal.png"] style:(UIBarButtonItemStylePlain) target:nil action:nil];
  2. self.navigationItem.backBarButtonItem = backItem;

看图:


第二个"<",就是自定的图片,这个自定义有意思吗?大家看着用吧

2.自定义视图无效!

  1. UIView * view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 30, 44)];
  2. view.backgroundColor = [UIColor colorWithRed:0.263 green:1.000 blue:0.311 alpha:1.000];
  3. UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithCustomView:view];
  4. self.navigationItem.backBarButtonItem = backItem;

3.自定义按钮~

注意这个相对第1个自定义照片的区别:backBarButtonItem不能用View视图方法自定义,而leftBarButtonItem可以哦!

  1. UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
  2. [button setImage:[UIImage imageNamed:@"navibar_back_btn_bg_normal.png"] forState:UIControlStateNormal];
  3. [button setFrame:CGRectMake(0, 0, 30, 44)];
  4. [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
  5. UIBarButtonItem * barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  6. self.navigationItem.<span style="color:#ff0000;">leftBarButtonItem</span> = barButtonItem;

这个自定义,根据【2】,可以知道其作用,在这里不在多说。

4.pop手势

  1. //官方文档:
  2. NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationController : UIViewController
  3. @property(nonatomic, assign) id<UINavigationControllerDelegate> delegate;
  4. @property(nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer NS_AVAILABLE_IOS(7_0);

以上的方法,都是基于系统自带的UINavigationController来自定义,如果不是系统的,比如淘宝的是自定义的UINavigation,所以没有利用系统的pop手势,而是自定义手势。又比如天猫的只用到【2】的改变图标,但文字都是统一的“返回”,并且部分页面,不用pop手势,直接弹回去。【分析于:2014.11.23日】

最后,大家都试试自定义自己的back按钮吧!如果你有更多更好的自定义方法,记得分享哦!还有很多细节我没有说到,如果大家感兴趣的,可以自己在深入研究一下哦~

4、附录:

【1】关于系统自带的“<”图标的官方解释:

  1. /*
  2. The back indicator image is shown beside the back button.
  3. The back indicator transition mask image is used as a mask for content during push and pop transitions
  4. Note: These properties must both be set if you want to customize the back indicator image.
  5. */
  6. @property(nonatomic,retain) UIImage *backIndicatorImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;
  7. @property(nonatomic,retain) UIImage *backIndicatorTransitionMaskImage NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;

根据上面文档:

1、只有这两个属性都设置了,才会显示自定义的图片。

2、这两个属性,只能用于iOS 7以上。

3、很多人问为什么要设置“backIndicatorTransitionMaskImage”这个属性,看官方文档就知道,当push、pop时显示的是这张image,但是疑问的是,当我设置这张照片跟“backIndicatorImage”属性的照片不一样时,系统不管是push,还是pop,还是完成时,都只会显示"backIndicatorImage"属性设置的照片。但由于文档没有更多信息,所以,这个问题我也就没有找到答案。

【2】参考一大神的总结:

UINavigationController Class Reference去,在“Updating the Navigation Bar”小节,有这么一段话:

The bar button item on the left side of the navigation bar allows for navigation back to the previous view controller on the navigation stack. The navigation controller updates the left side of the navigation bar as follows:

  • If the new top-level view controller has a custom left bar button item, that item is displayed. To specify a custom left bar button item, set the leftBarButtonItem property of the view controller’s navigation item.
  • If the top-level view controller does not have a custom left bar button item, but the navigation item of the previous view controller has a valid item in itsbackBarButtonItem property, the navigation bar displays that item.
  • If a custom bar button item is not specified by either of the view controllers, a default back button is used and its title is set to the value of the title property of the previous view controller—that is, the view controller one level down on the stack. (If there is only one view controller on the navigation stack, no back button is displayed.)

我大致解释一下,使用pushViewController切换到下一个视图时,navigation controller按照以下3条顺序更改导航栏的左侧按钮。

1、如果B视图有一个自定义的左侧按钮(leftBarButtonItem),则会显示这个自定义按钮;

2、如果B没有自定义按钮,但是A视图的backBarButtonItem属性有自定义项,则显示这个自定义项;

3、如果前2条都没有,则默认显示一个后退按钮,后退按钮的标题是A视图的标题。

   原文链接:http://zgia.net/?p=306

【3】关于判断处理说明,和判断系统版本代码

  1.说明:如果系统在7.0以上,那么由于有属性【1】,所以非常容易在A视图push前处理,但是iOS 6系统下,没有这个属性,又利用【2】原理,所以在B视图下,自定义一个leftBarButtonItem按钮,处理点击事件,这就是我目前所做到的,最好的方案。
  2.系统版本判断代码
  1. //检查系统版本
  2. #define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
  3. #define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
  4. #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
  5. #define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
  6. #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

官方文档:

  1. + (UIDevice *)currentDevice;
  2. @property(nonatomic,readonly,retain) NSString    *name;              // e.g. "My iPhone"
  3. @property(nonatomic,readonly,retain) NSString    *model;             // e.g. @"iPhone", @"iPod touch"
  4. @property(nonatomic,readonly,retain) NSString    *localizedModel;    // localized version of model
  5. @property(nonatomic,readonly,retain) NSString    *systemName;        // e.g. @"iOS"
  6. @property(nonatomic,readonly,retain) NSString    *systemVersion;     // e.g. @"4.0"
  7. @property(nonatomic,readonly) UIDeviceOrientation orientation;       // return current device orientation.  this will return UIDeviceOrientationUnknown unless device orientation notifications are being generated.
  8. @property(nonatomic,readonly,retain) NSUUID      *identifierForVendor NS_AVAILABLE_IOS(6_0);      // a UUID that may be used to uniquely identify the device, same across apps from a single vendor.

nice~

【转】自定义iOS的Back按钮(backBarButtonItem)和pop交互手势(interactivepopgesturerecognizer) --- 不错的更多相关文章

  1. iOS7自定义back按钮和pop交互手势

    Clambake for iPhone有一个回退按钮在所有的导航条上.这是一个简单的没有文字箭头. 实现一个自定义按钮是简单的.类似这个设置controller 的navigationItem一个le ...

  2. iOS 添加导航按钮

    iOS设置导航按钮navigationBar中包含了这几个重要组成部分:leftBarButtonItem, rightBarButtonItem, backBarButtonItem, title. ...

  3. iOS8自定义推送显示按钮及推送优化

    http://www.jianshu.com/p/803bfaae989e iOS8自定义推送显示按钮及推送优化 字数1435 阅读473 评论0 喜欢2 导语 在iOS8中,推送消息不再只是简单地点 ...

  4. 解决 ios7.0 以后自定义导航栏左边按钮靠右的问题

    解决 ios7.0 以后自定义导航栏左边按钮靠右的问题 www.111cn.net 编辑:edit02_lz 来源:转载 最近开发了一个ios的app,在ios7.0+出现自定义导航栏左边按钮出现靠右 ...

  5. UIBarButtonItem-添加自定义Left或者Right按钮

    为UINavigationController添加UINavigationItem,我们可以这样写:   1.添加返回导航按钮backBarButtonItem   1.用系统自带的返回按钮 UIBa ...

  6. UIBarButtonItem-添加自定义Left或者Right按钮 <总结>

    为UINavigationController添加UINavigationItem   1.添加返回导航按钮backBarButtonItem   1.用系统自带的返回按钮 UIBarButtonIt ...

  7. 微信小程序 修改(自定义) 单选/复选按钮样式 checkbox/radio样式自定义

    参考文章: 微信小程序 修改(自定义) 单选/复选按钮样式 checkbox/radio样式自定义

  8. 自定义jQuery Mobile工具栏按钮

    自定义jQuery Mobile工具栏按钮 1.实现效果

  9. Apple iOS 触控按钮 自动关闭 bug

    Apple iOS 触控按钮 自动关闭 bug bug 轻点 iPhone 背面可执行操作 您可以轻点两下或轻点三下 iPhone 背面以执行某些操作,如向上或向下滚动.截屏.打开"控制中心 ...

随机推荐

  1. 设置HTTP header方式

    一, Server Code JSP----> <%@ page language="java" contentType="text/html; charse ...

  2. IMP不到指定的表空间

    ==============================================================================只导dmp文件中的几个表数据,解决导入时ta ...

  3. Application.persistentDataPath 的一个小坑

    打包之前在Android的Player Setting里面选择WriteAccess (写入访问) Internal Only:表示Application.persistentDataPath的路径是 ...

  4. Lua 简单的IO交互 和迷宫代码

    function room1 () print("in room1") local move = io.read() if move == "south" th ...

  5. DataGrid行详细信息的绑定--DataGrid.RowDetailsTe(转载)

    在Silverlight中的DataGrid控件使用中我们想点击其中一行并且看这一行的详细信息应该如何做呢?而且这个详细信息是多行的数据,而非简单的几个属性. 在这里我们使用DataGrid.RowD ...

  6. 学习笔记--Git安装 创建版本库 图文详解

    一.Git下载 在Windows上安装git,一般为msysgit,官网地址:http://git-scm.com/ 我下载的是Git-1.9.2-preview20140411.exe 二.Git安 ...

  7. TortoiseSVN文件夹及文件图标不显示解决方法(转发)

    地址:http://blog.csdn.net/lishehe/article/details/8257545 由于自己的电脑是win7(64位)的,系统安装TortoiseSVN之后,其他的功能都能 ...

  8. Android中ContentProvider的简单使用

    1.新建继承ContentProvider的类 package com.wangzhu.demo; import android.content.ContentProvider; import and ...

  9. javaWEB邮件测试

    新建一个工具类: Mail.java 该类的主要关键点是:1.设置系统属性.也就是你是用什么协议来进行邮件发送的,邮件协议有很多在种,比如impt,smpt,prop等协议, 我现在测试用的是smpt ...

  10. linux上应用程序的执行机制

    linux上应用程序的执行机制 执行文件是如何在shell中被"执行"的.本文中尽可能少用一些源码,免得太过于无 聊,主要讲清这个过程,感兴趣的同学可以去查看相应的源码了解更多的信 ...