现在的位置: 首页 > 综合 > 正文

NavigationBar 完美自定义UIBarButtonItem

2017年12月09日 ⁄ 综合 ⁄ 共 3289字 ⁄ 字号 评论关闭

相信大家在开发ios应用的时候都会遇到过想修改NavigationBar上面的左右按钮的情况,这是一个很常见的需求。本人在开发的过程中也遇到过了这个情况。我简单地描述一下我遇到问题的过程

1.既然时要自定义backBarButton,因为backBarButton时UIBarButtonItem类型,所以我的第一个想法就是自定义一个UIBarButtonItem类型的对象,然后把这个对象赋值给self.navigationItem.backBarButtonItem.以下为我实现的代码:

    UIBarButtonItem *rbtn = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"u60.png"] style:UIBarButtonItemStylePlain target:nil action:nil];

    self.navigationItem.backBarButtonItem=rbtn;

(注:在使用NavigationController的pushController方法将一个ViewController添加到NavigationController的栈顶时,栈顶的ViewController的NavigationBar中会自动生成一个BackBarItem,其样式为一个向左的箭头,加前一个back title)

这时问题来了,系统自动生成的backBarButtonItem的确变成了自己自定义的图片,但是backBarButtonItem还是保留了原来的向左的箭头。所以,这个方法是没有办法实现完全自定义backBarButtonItem

效果如下:

2.既然是这样,我就开始想为什么向左的箭头会一直存在呢?后来试了很多个方法,最终发现,当设置好自定义的UIBarButtonItem的backButtonBackgroudImage后再赋值给self.navigationItem.backButtonItem,那个自定义生成的向左的箭头就会被替代掉了,随即生成的是自己自定义的图片,代码如下:

    UIBarButtonItem *rbtn = [[UIBarButtonItem alloc]initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];

    [rbtn setBackButtonBackgroundImage:[UIImage imageNamed:@"u60.png"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
    
    self.navigationItem.backBarButtonItem=rbtn;

效果如下:

可以见到,那个向左的箭头已经不见了,但是图片会有被拉伸的感觉,这需要自己去调整,可以通过

 UIImage *backButtonImage = [[UIImage imageNamed:@"u60.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];

先设定好图片的拉伸,再用来setBackButtonBackgroundImage,至于EdgeInsets的使用,我怎么也学不会,具体的可参考http://blog.csdn.net/liubo5290392/article/details/21099221,其实也就是如何拉伸一个图片。

但是,这个拉伸的效果很不好,而且可以看到,其实这个自定义的按钮还是需要有标题的,只不过我把标题给设空了,所以看不到有标题,而且一旦设置了标题,你自定义的图片的拉伸情况也会发生改变的,你又需要乱七八糟地调一通,才可能勉强把图给调出来,非常的麻烦,可能有大神会知道这个调整的过程是怎样的操作的,也请指教。所以说,这种方法是勉强可以实现了,但是效率很低,也自定义得不够彻底,因为还会出现以下得情况。

3.按钮的可点击范围太大,即使点击空白的地方,也会触发按钮

  就拿上 面的图来说,我想实现的效果是点击图片的时候按钮被触发,但是实际上是点击了图片右边很远的空白地方,按钮都会被触发。这个问题我花了大概8个小时的时间去试各种方法,但是还是达不到效果,我记得有一个方法就是backBarButtonItem有个width属性,这个坑爹的属性,让你觉得好像改了就能改变这个触发宽度一样,但是还是不行的。其中有一个种方法让我看到了希望,这也是网上解释的最多的自定义navigationbar按钮方法,就是利用UIBarButtonItem的initWithCustomView方法,即先设置好一个按钮,当然可以设置好它的Frame,然后再通过initWithCustomVIew的方法把自定义的按钮设置进去。这种方法于理来说是非常好的,也能达到设置的效果,但是还是同样的问题,点击空白的地方也会触发按钮,令人觉得非常难受。

后了找了很久才找到以下的方法:

    UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 22, 22)];
    UIButton *button = [[UIButton alloc] initWithFrame:contentView.bounds];
    [button setBackgroundImage:[UIImage imageNamed:@"u60.png"] forState:UIControlStateNormal];
    [button addTarget:self action:@selector(onBarBtn:) forControlEvents:UIControlEventTouchUpInside];
    [contentView addSubview:button];
    UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:contentView];
    self.navigationItem.leftBarButtonItem = barButtonItem;

这个方法的简述大概就是先创建一个UIView,然后再UIView里面放一个UIButton,最后再用initWithCustomeView方法把自定义的UIView设置进去。到这里,只点击图片区域能触发按钮的功能终于实现了,我们可以完全自定义自己的按钮了。

但是关于为什么给UIButton包多一层UIView就能实现避免这个问题,我也无从找到答案,但是我个人的理解是:因为UIButton是不能直接作为一个主View出现的,就好比一个Nib文件,UIButton也只能被包含在一个UIView内,而NavigationBar中的左右按钮,它需要呈现的是一个UIView,虽然UIButton也是继承自UIView,但是就如我上面所说,它只能以被UIView包含的形式显示,若直接把UIButton传给initWithCustomView的方法,系统还是会自动生成一个UIView来包含UIButton,所以无论我们怎么改UIButton的大小,都无法改动得了那个自动生成UIView得大小,这也就是问什么我们点了按钮以外空白的地方也会触发按钮的原因,因为我们点击的空白区域,实际上是包含了自定义按钮的,系统自动生成的UIView,也就是左右按钮实际上的View,而不只是你设置的UIButton。

以上是我自己的理解,不知道是否正确,但这个方法的确可以完成完全自定义NavigationBar 的左右按钮了,当然如果有哪个大神可以告诉我正确的原因,我会非常感激的。这个过程花了我很多时间,也不知道是否值得,但是我是强迫症患者,不解决的话自己又受不了,所以作下记录,希望能帮到遇到同样问题的大家,也为了自己以后遇到同样的问题知道怎么解决。

抱歉!评论已关闭.