支付宝NavBar模拟中遇到的问题及解决办法

前言 在模拟支付宝的过程中,遇到的第一个问题就是NavBar的实现,一开始打算的是自定义NavBar,但是在push和pop的时候没有了原版的动画效果,所以决定用系统自带的方法完成。接下来讲一下过程。
下面是两者的效果图。

支付宝NavBar模拟中遇到的问题及解决办法
文章图片
自定义bar.png 支付宝NavBar模拟中遇到的问题及解决办法
文章图片
系统方法bar.png 正文 左侧账单按钮实现 首先是左边的账单按钮,代码如下:

UIButton *leftBtn = [UIButton new]; leftBtn.frame = CGRectMake(0, 0, 60, 32); [leftBtn setImage:[[UIImage imageNamed:@"home_bill"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forState:UIControlStateNormal]; [leftBtn setTitle:@"账单" forState:UIControlStateNormal]; leftBtn.titleLabel.font = [UIFont systemFontOfSize:14]; [leftBtn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateHighlighted]; [leftBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; UIBarButtonItem *leftBarButton = [[UIBarButtonItem alloc] initWithCustomView:leftBtn]; self.navigationItem.leftBarButtonItem = leftBarButton;

界面如下:
支付宝NavBar模拟中遇到的问题及解决办法
文章图片
bar1.png 但是发现两个问题:
1、图片和文字考的太近,这个简单,只需要设置一下按钮的inset。具体可以看另一篇文章:Button的titleEdgeInsets和imageEdgeInsets
[leftBtn setImageEdgeInsets:UIEdgeInsetsMake(0, 6, 0, 0)]; [leftBtn setTitleEdgeInsets:UIEdgeInsetsMake(0, 12, 0, 0)];

效果蛮好,

支付宝NavBar模拟中遇到的问题及解决办法
文章图片
bar2.png 2、账单按钮太靠右
想让按钮靠左,其实也不复杂。代码:
UIBarButtonItem *leftSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; leftSpace.width = - 16.0f; self.navigationItem.leftBarButtonItems = @[leftSpace, leftBarButton];

大致的解释一下代码,其实就是传建一个width为-16的item来占位,因为宽度为负数,所以leftBarButton不仅不会向右移,反而向左移了。
需要注意的是,这里我设置的width为-16.0f刚好为leftBarButtonItem的x。举个例子:设置width为-15.0f:

支付宝NavBar模拟中遇到的问题及解决办法
文章图片
bar3.png
虽然不是很清楚,但是隐约可以看到按钮左侧仍有一个像素的宽度。
好了,左侧按钮完成:
支付宝NavBar模拟中遇到的问题及解决办法
文章图片
bar4.png 右侧两个按钮实现 接下来要实现的是右侧两个按钮,我第一时间想到的就是使用rightBarButtonItems。来试一下:
UIBarButtonItem *rightAddItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"add_tag_reverse"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:nil]; UIBarButtonItem *rightContactItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"home_contacts"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:nil]; self.navigationItem.rightBarButtonItems = @[rightAddItem, rightContactItem];

支付宝NavBar模拟中遇到的问题及解决办法
文章图片
bar5.png
恩,两个按钮距离太远了,我就想到了刚刚账单按钮的方法,创建一个占位按钮,我们来试一下。
UIBarButtonItem *rightSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; rightSpace.width = -16.0f; self.navigationItem.rightBarButtonItems = @[rightAddItem, rightSpace,rightContactItem];

支付宝NavBar模拟中遇到的问题及解决办法
文章图片
bar6.png
显然没什么效果,因为好奇我又换了一下items的顺序,把占位item放到最前看看有没有效果:
self.navigationItem.rightBarButtonItems = @[rightSpace, rightAddItem, rightContactItem];

支付宝NavBar模拟中遇到的问题及解决办法
文章图片
bar7.png
有效果,这样看来放在两个item中间是没什么效果的。那怎么该怎么实现呢?
其实一开始我也是各种百度各种搜索,但是怎么也找不到我这么细节的问题,后来在贤者时间才想到的。
解决办法就是把这两个按钮放在一个view上,再设置view为leftItems的其中一个,这样就可以自由控制按钮的位置啦。
UIView *btnView = [UIView new]; btnView.frame = CGRectMake(0, 0, 64, 32); btnView.backgroundColor = [UIColor clearColor]; UIButton *addBtn = [UIButton new]; addBtn.frame = CGRectMake(32, 0, 32, 32); [addBtn setImage:[UIImage imageNamed:@"add_tag_reverse"] forState:UIControlStateNormal]; [btnView addSubview:addBtn]; UIButton *personBtn = [UIButton new]; personBtn.frame = CGRectMake(0, 0, 32, 32); [personBtn setImage:[UIImage imageNamed:@"home_contacts"] forState:UIControlStateNormal]; [btnView addSubview:personBtn]; UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithCustomView:btnView]; UIBarButtonItem *rightSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; rightSpace.width = -16.0f; self.navigationItem.rightBarButtonItems = @[rightSpace, rightBarButton];

代码很清楚,就不再说了。
支付宝NavBar模拟中遇到的问题及解决办法
文章图片
bar8.png 搜索栏实现 首先我们得先了解titleView到底是怎么放的。先做几个实验。实验代码如下且类似,但是会改变titleView的高度和宽度。
UIView *titleView = [UIView new]; titleView.frame = CGRectMake(0, 0, kWidth, 200); titleView.backgroundColor = [UIColor greenColor]; self.navigationItem.titleView = titleView;

下面是效果图:
支付宝NavBar模拟中遇到的问题及解决办法
文章图片
(10,200).png 支付宝NavBar模拟中遇到的问题及解决办法
文章图片
(320,10).png 支付宝NavBar模拟中遇到的问题及解决办法
文章图片
(320,200).png 支付宝NavBar模拟中遇到的问题及解决办法
文章图片
不设置右侧item.png 支付宝NavBar模拟中遇到的问题及解决办法
文章图片
右侧item的宽为200.png 可以发现,当titleView的宽度大于一定的值后,
titleView的宽就不会再大了,这个值取决于左右侧的item的宽度。
知道了这些就有助于设置searchBar了。
searchBar的实现比较简单,不多说,直接放代码。
UITextField *searchBar = [UITextField new]; searchBar.frame = CGRectMake(0, 0, kWidth, 28); searchBar.layer.cornerRadius = 2; searchBar.font = [UIFont systemFontOfSize:14]; UIImageView *searchBarLeftView = [UIImageView new]; searchBarLeftView.frame = CGRectMake(12, 7, 14, 14); searchBarLeftView.image = [UIImage imageNamed:@"front_search_icon"]; [searchBar addSubview:searchBarLeftView]; UIImageView *searchBarRightView = [UIImageView new]; searchBarRightView.frame = CGRectMake(160, 6.5, 10, 15); searchBarRightView.image = [UIImage imageNamed:@"ap_titlebar_search_voice"]; [searchBar addSubview:searchBarRightView]; searchBar.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 0)]; searchBar.leftViewMode = UITextFieldViewModeAlways; searchBar.backgroundColor = [UIColor colorWithRed:47/255.0 green:141/255.0 blue:214/255.0 alpha:1.0]; searchBar.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"搜索" attributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]; searchBar.borderStyle = UITextBorderStyleNone; self.navigationItem.titleView = searchBar;

最后 【支付宝NavBar模拟中遇到的问题及解决办法】温馨提示:能用系统的那就尽量别自定义了啊喂!

    推荐阅读