注:本文章内容已过时,不适合iOS12及更高的系统版本
iOS 11中,系统重构了导航栏,UINavigationBar的层次结构发生了变化,同时影响了按钮UINavigationItem的布局位置以及响应区域。而针对于不同的系统,我们很多时候可能都需要做导航栏按钮的响应区域的优化。
本文会针对两个case来做导航栏响应区域的优化。
case 1:iOS11以下系统导航栏按钮响应区域过大
该case是在相册选择页面,导航栏右上角有一个取消按钮,而视图展示的是当前相册中的图片以及每个图片右上角有一个可选择的按钮。
我们是通过[[UIBarButtonItem alloc] initWithCustomView:button]
的方式来生成一个UIBarButtonItem
对象的,我们可以看到按钮的实际大小是绿色区域部分,而它的点击响应范围则是红色框中的任意位置。这样当我们点击第一行最后一个照片的选择按钮时,会触发点击取消的操作,导致无法正常选择。
通常方案
要解决这个问题大多数方案都是把UIButton
放到一个UIView
中,设置View的clipsToBounds
以及userInteractionEnabled
属性,即可实现缩小点击区域,代码如下
UIButton *button = [[UIButton alloc] init];
[button setTitle:@"取消" forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize:15.0f];
[button sizeToFit];
[button addTarget:self action:@selector(cancelBtnClicked) forControlEvents:UIControlEventTouchUpInside];
UIView * view = [[UIView alloc] initWithFrame:button.frame];
view.userInteractionEnabled = YES;
view.clipsToBounds = YES;
[view addSubview:button];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
这样修改后,按钮的响应区域变成了这个样子。
我们发现,当前的响应区域不会覆盖到图片的选择按钮了,但是还是超过了导航栏本身,在小分辨率手机上依然存在误触的情况,同时在导航栏上的相应区域也变小了,这样可能会导致取消按钮本身的点击响应变得不灵敏。
更好的方式
我们继续使用UIButton
来初始化一个UIBarButtonItem
,不需要在外层嵌套一个UIView
。但我们需要重写UINavigationBar
的hitTest
方法,设置当点击导航栏之外时不响应,即可解决问题。
@implementation UINavigationBar (TGL)
+ (void)load
{
[UINa