iOS开发项目篇—04添加导航栏的按钮
一、设置导航栏的按钮
要求实现的效果:
说明:默认状态下和高亮状态下的图片是不一样的。
按钮的图片需要设置默认状态和高亮状态时的显示,系统了提供的下面方法
viewController.navigationItem.leftBarButtonItem=[UIBarButtonItem alloc]initWithImage:<#(UIImage *)#> style:<#(UIBarButtonItemStyle)#> target:<#(id)#> action:<#(SEL)#>
在这里,我们需要设置两种状态下的图片,显然该方法无法满足我们的需求。那么我们就位UIBarButtonItem增加一个分类,扩充一个方法,让其能够设置两种状态下的两张图片。
1 // 2 // UIBarButtonItem+Extension.m 3 // 04-微博导航栏上的按钮 4 // 5 // Created by apple on 14-7-4. 6 // 7 // 8 9 #import "UIBarButtonItem+Extension.h" 10 11 @implementation UIBarButtonItem (Extension) 12 +(UIBarButtonItem *)itemWithImageName:(NSString *)ImageName highImageName:(NSString *)highImageName target:(id)target action:(SEL)action 13 { 14 //自定义UIView 15 UIButton *btn=[[UIButton alloc]init]; 16 17 //设置按钮的背景图片(默认/高亮) 18 [btn setBackgroundImage:[UIImage imageWithName:ImageName] forState:UIControlStateNormal]; 19 [btn setBackgroundImage:[UIImage imageWithName:highImageName] forState:UIControlStateHighlighted]; 20 21 //设置按钮的尺寸和图片一样大,使用了UIImage的分类 22 btn.size=btn.currentBackgroundImage.size; 23 [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; 24 25 return [[UIBarButtonItem alloc]initWithCustomView:btn]; 26 27 } 28 @end
二、回退和跳转到首页
1.要求实现的效果:
程序启动后,显示的首页界面:
点击界面导航栏左角的按钮,跳转到ONE(注意导航栏上两边的按钮)
点击“跳转到Two”按钮,跳转到Two(注意导航栏上右边的按钮)
点击“跳转到Three”按钮,跳转到Three
说明:点击导航栏左边的回退按钮(《---)可以返回上一个界面,点击导航栏右边的按钮(···)可以回到相应的首页。
点击THree中导航栏右边的按钮,回到home首页
消息界面:
点击cell,跳转到一个新的界面(注意导航栏上得按钮)
说明:在项目中有多个子页面的导航栏,都需要用到回到上一页和跳到首页这一对BarButtonItem,我们知道导航栏上的按钮设定需要设定对应的导航控制器来完成,要统一导航栏中在很多地方都用到的按钮。
2.下面介绍三种实现的方法
(1)比较笨的实现方法是,在每个对应的页面都实现一次下面的方法。
如果是100个页面需要这样的导航栏,那么就需要把相同的代码拷贝100份到相应的页面,有必要吗?这种方法确实可以实现,可总是相同的代码,未免过于垃圾。
(2)抽出一个父类
把公共代码抽取到基本控制器中(抽取公共的父类),这种做法虽然能够实现功能,但是这种做法是有问题的,不能这么做。
所谓问题:继承了UITableViewController就不能继承基础父类。
用继承不能保证所有的控制器都继承公共的父类,所以不能使用继承,一般继承自系统的控制器就好了,不要有继承约束。
说明: 在iOS中控制器很少用继承,因为ios中提供了多种控制器
(3)拦截push操作
通过分析,我们可以通过直接在自定义的导航控制器中进行设置,拦截push操作。当push的时候,对栈进行判断,只要当前push的不是栈底的控制器,那么就统一设置导航栏的leftBarButtonItem和rightBarButtonItem,在他们的监听方法中分别完成回到前一页和回到首页操作。
1 -(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated 2 { 3 //如果现在push的不是栈顶控制器,那么久隐藏tabbar工具条 4 if (self.viewControllers.count>0) { 5 viewController.hidesBottomBarWhenPushed=YES; 6 7 //拦截push操作,设置导航栏的左上角和右上角按钮 8 viewController.navigationItem.leftBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_back" highImageName:@"navigationbar_back_highlighted" target:self action:@selector(back)]; 9 viewController.navigationItem.rightBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_more" highImageName:@"navigationbar_more_highlighted" target:self action:@selector(more)]; 10 11 } 12 [super pushViewController:viewController animated:YES]; 13 } 14 15 -(void)back 16 { 17 #warning 这里用的是self, 因为self就是当前正在使用的导航控制器 18 [self popViewControllerAnimated:YES]; 19 } 20 21 -(void)more 22 { 23 [self popToRootViewControllerAnimated:YES]; 24 }
如果在某个页面中,我们不需要系统设定的导航栏按钮,那么可以直接在相应的页面对导航栏的leftBarButtonItem和rightBarButtonItem进行重新设置,覆盖系统设置。
如Two界面,导航栏右边的按钮,代码如下:
1 //重置导航栏右上角的按钮,以覆盖系统统一的方案 2 -(void)viewDidLoad 3 { 4 [super viewDidLoad]; 5 6 self.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc]initWithTitle:@"真的可以设置" style:UIBarButtonItemStyleDone target:self action:nil]; 7 }
提示:自定义导航控制器的优点~能够拦截到很多操作。
3.第三种方法的实现
(1)导入必要的图片资源
说明:硬盘对硬盘的拷贝
(2)新建三个页面,演示效果
设置点击按钮后跳转的代码:
1 // 2 // YYOneViewController.m 3 // 04-微博导航栏上的按钮 4 // 5 // Created by apple on 14-7-4. 6 // 7 // 8 9 #import "YYOneViewController.h" 10 #import "YYTwoViewController.h" 11 12 @interface YYOneViewController () 13 - (IBAction)jump2Two; 14 15 @end 16 17 @implementation YYOneViewController 18 19 //点击按钮跳转到第二个界面 20 - (IBAction)jump2Two { 21 YYTwoViewController *two=[[YYTwoViewController alloc]init]; 22 two.title=@"Two"; 23 [self.navigationController pushViewController:two animated:YES]; 24 } 25 @end
三、实现代码
1.UIImage的分类,扩充方法:
UIImage+Extension.h文件
1 // 2 // UIImage+Extension.h 3 // 4 // 5 // Created by apple on 14-7-3. 6 // 7 // 8 9 #import <UIKit/UIKit.h> 10 11 @interface UIImage (Extension) 12 + (UIImage *)imageWithName:(NSString *)name; 13 @end
UIImage+Extension.m文件
1 // 2 // UIImage+Extension.m 3 // 4 // 5 // Created by apple on 14-7-3. 6 // 7 // 8 9 #import "UIImage+Extension.h" 10 11 @implementation UIImage (Extension) 12 + (UIImage *)imageWithName:(NSString *)name 13 { 14 UIImage *image = nil; 15 if (iOS7) { // 处理iOS7的情况 16 NSString *newName = [name stringByAppendingString:@"_os7"]; 17 image = [UIImage imageNamed:newName]; 18 } 19 20 if (image == nil) { 21 image = [UIImage imageNamed:name]; 22 } 23 return image; 24 } 25 @end
2.UIBarButtonItem的分类,扩充方法:
UIBarButtonItem+Extension.h文件
1 // UIBarButtonItem+Extension.h 2 // 04-微博导航栏上的按钮 3 // 4 // Created by apple on 14-7-4. 5 6 7 #import <UIKit/UIKit.h> 8 9 @interface UIBarButtonItem (Extension) 10 +(UIBarButtonItem *)itemWithImageName:(NSString *)ImageName highImageName:(NSString *)highImageName target:(id)target action:(SEL)action; 11 @end
UIBarButtonItem+Extension.m文件
1 // 2 // UIBarButtonItem+Extension.m 3 // 04-微博导航栏上的按钮 4 // 5 // 6 7 #import "UIBarButtonItem+Extension.h" 8 9 @implementation UIBarButtonItem (Extension) 10 +(UIBarButtonItem *)itemWithImageName:(NSString *)ImageName highImageName:(NSString *)highImageName target:(id)target action:(SEL)action 11 { 12 //自定义UIView 13 UIButton *btn=[[UIButton alloc]init]; 14 15 //设置按钮的背景图片(默认/高亮) 16 [btn setBackgroundImage:[UIImage imageWithName:ImageName] forState:UIControlStateNormal]; 17 [btn setBackgroundImage:[UIImage imageWithName:highImageName] forState:UIControlStateHighlighted]; 18 19 //设置按钮的尺寸和图片一样大,使用了UIImage的分类 20 btn.size=btn.currentBackgroundImage.size; 21 [btn addTarget:target action:action forControlEvents:UIControlEventTouchUpInside]; 22 23 return [[UIBarButtonItem alloc]initWithCustomView:btn]; 24 25 } 26 @end
3..UIView的分类,扩充方法:
UIView+Extension.h文件
1 // 2 // UIView+Extension.h 3 // 4 5 #import <UIKit/UIKit.h> 6 7 @interface UIView (Extension) 8 @property (nonatomic, assign) CGFloat x; 9 @property (nonatomic, assign) CGFloat y; 10 @property (nonatomic, assign) CGFloat width; 11 @property (nonatomic, assign) CGFloat height; 12 @property (nonatomic, assign) CGSize size; 13 @end
UIView+Extension.m文件
1 // 2 // UIView+Extension.m 3 // 4 5 #import "UIView+Extension.h" 6 7 @implementation UIView (Extension) 8 9 - (void)setX:(CGFloat)x 10 { 11 CGRect frame = self.frame; 12 frame.origin.x = x; 13 self.frame = frame; 14 } 15 16 - (CGFloat)x 17 { 18 return self.frame.origin.x; 19 } 20 21 - (void)setY:(CGFloat)y 22 { 23 CGRect frame = self.frame; 24 frame.origin.y = y; 25 self.frame = frame; 26 } 27 28 - (CGFloat)y 29 { 30 return self.frame.origin.y; 31 } 32 33 - (void)setWidth:(CGFloat)width 34 { 35 CGRect frame = self.frame; 36 frame.size.width = width; 37 self.frame = frame; 38 } 39 40 - (CGFloat)width 41 { 42 return self.frame.size.width; 43 } 44 45 - (void)setHeight:(CGFloat)height 46 { 47 CGRect frame = self.frame; 48 frame.size.height = height; 49 self.frame = frame; 50 } 51 52 - (CGFloat)height 53 { 54 return self.frame.size.height; 55 } 56 57 - (void)setSize:(CGSize)size 58 { 59 // self.width = size.width; 60 // self.height = size.height; 61 CGRect frame = self.frame; 62 frame.size = size; 63 self.frame = frame; 64 } 65 66 - (CGSize)size 67 { 68 return self.frame.size; 69 } 70 71 @end
4.核心代码,拦截push操作
YYUINavigationViewController.m文件
1 // 2 // YYUINavigationViewController.m 3 // 4 5 #import "YYNavigationViewController.h" 6 7 @interface YYNavigationViewController () 8 9 @end 10 11 @implementation YYNavigationViewController 12 13 - (void)viewDidLoad 14 { 15 [super viewDidLoad]; 16 } 17 18 -(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated 19 { 20 //如果现在push的不是栈顶控制器,那么久隐藏tabbar工具条 21 if (self.viewControllers.count>0) { 22 viewController.hidesBottomBarWhenPushed=YES; 23 24 //拦截push操作,设置导航栏的左上角和右上角按钮 25 viewController.navigationItem.leftBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_back" highImageName:@"navigationbar_back_highlighted" target:self action:@selector(back)]; 26 viewController.navigationItem.rightBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_more" highImageName:@"navigationbar_more_highlighted" target:self action:@selector(more)]; 27 28 } 29 [super pushViewController:viewController animated:YES]; 30 } 31 32 -(void)back 33 { 34 #warning 这里用的是self, 因为self就是当前正在使用的导航控制器 35 [self popViewControllerAnimated:YES]; 36 } 37 38 -(void)more 39 { 40 [self popToRootViewControllerAnimated:YES]; 41 } 42 43 @end
5.首页的主控制器代码,设置首页的导航栏按钮
YYHomeTableViewController.m文件
1 // 2 // YYHomeTableViewController.m 3 // 4 5 #import "YYHomeTableViewController.h" 6 #import "YYOneViewController.h" 7 8 @interface YYHomeTableViewController () 9 10 @end 11 12 @implementation YYHomeTableViewController 13 14 - (id)initWithStyle:(UITableViewStyle)style 15 { 16 self = [super initWithStyle:style]; 17 if (self) { 18 // Custom initialization 19 } 20 return self; 21 } 22 23 - (void)viewDidLoad 24 { 25 [super viewDidLoad]; 26 27 //设置导航栏的按钮 28 self.navigationItem.leftBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_friendsearch" highImageName:@"navigationbar_friendsearch_highlighted" target:self action:@selector(friendsearch)]; 29 self.navigationItem.rightBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_pop" highImageName:@"navigationbar_pop_highlighted" target:self action:@selector(pop)]; 30 } 31 -(void)pop 32 { 33 YYLog(@"---POP---"); 34 } 35 -(void)friendsearch 36 { 37 //跳转到one这个子控制器界面 38 YYOneViewController *one=[[YYOneViewController alloc]init]; 39 one.title=@"One"; 40 //拿到当前控制器 41 [self.navigationController pushViewController:one animated:YES]; 42 43 } 44 45 #pragma mark - Table view data source 46 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 47 { 48 return 20; 49 } 50 51 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 52 { 53 static NSString *ID = @"cell"; 54 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 55 if (!cell) { 56 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; 57 } 58 cell.textLabel.text = [NSString stringWithFormat:@"%d----首页测试数据", indexPath.row]; 59 return cell; 60 } 61 62 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 63 { 64 //点击cell的时候,跳到下一个界面 65 UIViewController *newVc = [[UIViewController alloc] init]; 66 newVc.view.backgroundColor = [UIColor redColor]; 67 newVc.title = @"新控制器"; 68 [self.navigationController pushViewController:newVc animated:YES]; 69 } 70 71 @end
6.Two代码
YYTwoViewController.m文件
1 // 2 // YYTwoViewController.m 3 // 4 5 #import "YYTwoViewController.h" 6 #import "YYThreeViewController.h" 7 8 @interface YYTwoViewController () 9 - (IBAction)jump2Three; 10 11 @end 12 13 @implementation YYTwoViewController 14 15 16 //重置导航栏右上角的按钮,以覆盖系统统一的方案 17 -(void)viewDidLoad 18 { 19 [super viewDidLoad]; 20 21 self.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc]initWithTitle:@"真的可以设置" style:UIBarButtonItemStyleDone target:self action:nil]; 22 } 23 //点击按钮,跳转到第三个界面 24 - (IBAction)jump2Three { 25 YYThreeViewController *three=[[YYThreeViewController alloc]init]; 26 three.title=@"Three"; 27 [self.navigationController pushViewController:three animated:YES]; 28 } 29 @end
7.项目的PCH文件
1 // 2 // Prefix header 3 // 4 // The contents of this file are implicitly included at the beginning of every source file. 5 // 6 7 #import <Availability.h> 8 9 #ifndef __IPHONE_5_0 10 #warning "This project uses features only available in iOS SDK 5.0 and later." 11 #endif 12 13 #ifdef __OBJC__ 14 #import <UIKit/UIKit.h> 15 #import <Foundation/Foundation.h> 16 #import "UIImage+Extension.h" 17 #import "UIBarButtonItem+Extension.h" 18 #import "UIView+Extension.h" 19 20 #ifdef DEBUG // 调试状态, 打开LOG功能 21 #define YYLog(...) NSLog(__VA_ARGS__) 22 #else // 发布状态, 关闭LOG功能 23 #define YYLog(...) 24 #endif 25 26 27 // 随机色 28 #define YYRandomColor [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0] 29 30 // 是否为iOS7 31 #define iOS7 ([[UIDevice currentDevice].systemVersion doubleValue] >= 7.0) 32 #endif
四、补充说明
(1)mac--->ios
如果打开一个以前的项目,项目明明是一个ios项目,但是却显示为mac项目:
调整办法如下:
找到存储路径,右键显示包内容
包里的文件显示如下:
其中xcuserdata相当于是缓存,把该文件删除之后,重新打开项目即可。
(2)关于log的打印
在pch文件中,进行条件编译
1 #ifdef DEBUG // 调试状态, 打开LOG功能 2 #define YYLog(...) NSLog(__VA_ARGS__) 3 #else // 发布状态, 关闭LOG功能 4 #define YYLog(...) 5 #endif
在需要使用Nslog打印的时候,直接使用YYlog即可。
(3)设置导航栏为黑色不透明
btn.size = btn.currentBackgroundImage.size;
【property ‘size’ not found on object of type ‘UIButton】
或许可以用CGRect frame = btn.frame;
frame.size = btn.currentBackgroundImage.size;
btn.frame = frame;
代替。