IOS--- NavigationBar标题按钮

来源:互联网 发布:程序员加班傻 编辑:程序博客网 时间:2024/05/02 04:25
A.NavigationBar标题按钮
1.需求
  • 在“首页”的导航栏中部设置一个“首页”文字+箭头按钮
  • 统一设置样式
  • 根据实际文本长度调整宽度
  • 消除系统自带的点击高亮效果
  • 点击按钮,箭头上下颠倒
github: https://github.com/hellovoidworld/HVWWeibo
 
NavigationTitleButton
 
2.思路
  • 使用UIButton,设置文本和图片
  • 在initWithFrame统一样式
  • 创建一个继承UIButton的自定义类,重写文本和图片的绘图方法,互换位置
  • 设置一个标识成员变量,判断当前的按钮状态(弹出 or 缩回)
 
3.实现
(1)自定义继承UIButton的类 HVWNavigationBarTitleButton
复制代码
 1 // 2 //  HVWNavigationBarTitleButton.m 3 //  HVWWeibo 4 // 5 //  Created by hellovoidworld on 15/2/2. 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved. 7 // 8  9 #import "HVWNavigationBarTitleButton.h"10 11 @implementation HVWNavigationBarTitleButton12 13 /** 重写initWithFrame, 统一设置按钮的样式 */14 - (instancetype)initWithFrame:(CGRect)frame {15     if (self = [super initWithFrame:frame]) {16         // 设置字体17         self.titleLabel.font = HVWNavigationTitleFont;18         [self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];19        20         // 文本右对齐21         [self.titleLabel setTextAlignment:NSTextAlignmentRight];22        23         // 取消图标高亮效果24         [self setAdjustsImageWhenDisabled:NO];25        26         // 图片居中27         [self.imageView setContentMode:UIViewContentModeCenter];28        29     }30    31     return self;32 }33 34 /** 重写iamge的绘图方法 */35 - (CGRect)imageRectForContentRect:(CGRect)contentRect {36     CGFloat height = contentRect.size.height;37     CGFloat width = height;38     CGFloat x = self.size.width - width;39     CGFloat y = 0;40     return CGRectMake(x, y, width, height);41 }42 43 /** 重写title的绘图方法 */44 - (CGRect)titleRectForContentRect:(CGRect)contentRect {45     CGFloat height = contentRect.size.height;46     // 文本宽度 = 按钮整体宽度 - 图片宽度47     CGFloat width = self.height - height;48     CGFloat x = 0;49     CGFloat y = 0;50     return CGRectMake(x, y, width, height);51 }52 53 @end
复制代码
 
(2)在“首页”控制器设置“标题按钮”:
HVWHomeViewController.m:
复制代码
 1 - (void)viewDidLoad { 2     [super viewDidLoad]; 3     4     // 添加导航控制器按钮 5     // 左边按钮 6     self.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithImage:@"navigationbar_friendsearch" hightlightedImage:@"navigationbar_friendsearch_highlighted" target:self selector:@selector(searchFriend)]; 7     8     // 右边按钮 9     self.navigationItem.rightBarButtonItem = [UIBarButtonItem itemWithImage:@"navigationbar_pop" hightlightedImage:@"navigationbar_pop_highlighted" target:self selector:@selector(pop)];10    11     // 设置标题按钮12     HVWNavigationBarTitleButton *titleButton = [[HVWNavigationBarTitleButton alloc] init];13     titleButton.height = 35;14     titleButton.width = 100;15     [titleButton setTitle:@"首页" forState:UIControlStateNormal];16     [titleButton setImage:[UIImage imageWithNamed:@"navigationbar_arrow_down"] forState:UIControlStateNormal];17     // 设置背景图片18     [titleButton setBackgroundImage:[UIImage resizedImage:@"navigationbar_filter_background_highlighted"] forState:UIControlStateHighlighted];19    20     // 监听按钮点击事件,替换图标21     [titleButton addTarget:self action:@selector(titleButtonClickd:) forControlEvents:UIControlEventTouchUpInside];22    23     self.navigationItem.titleView = titleButton;24 }25  26 /** 标题栏按钮点击事件 */27 - (void) titleButtonClickd:(UIButton *) button {28     self.titleButtonExtended = !self.titleButtonExtended;29    30     if (self.isTitleButtonExtended) {31         [button setImage:[UIImage imageWithNamed:@"navigationbar_arrow_up"] forState:UIControlStateNormal];32     } else {33         [button setImage:[UIImage imageWithNamed:@"navigationbar_arrow_down"] forState:UIControlStateNormal];34     }35 }36  37 #mark:有希望依赖图片缓存,使用"=="判断当前按钮图片来决定按钮状态的,发现使用currentImage和新建一个UIImage(同一张图片)出来的地址并不一致!所以不能采用。38 -(void)titleButtonClick:(UIButton *)titleButton39 {40     UIImage *titleImage=[UIImage imageWithName:@"navigationbar_arrow_down"];41    42     if (titleButton.currentImage==titleImage) {43         //换成箭头向上44         [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_up"] forState:UIControlStateNormal];45     }else46     {47         //换成箭头向下48         [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal];49     }50 }
复制代码
 
B.导航栏标题按钮弹出框
1.需求
点击导航栏标题按钮弹出一个框
点击框外的其他地方,隐藏此框
 
HVWPopMenu
 
2.思路
因为框的范围涉及到了导航栏,所以不能放在导航栏下的内容界面控制器上,要放在导航栏上
在框和导航栏的夹层放置一个全屏的(透明/半透明)的UIButton,用来监听框外点击
封装此功能,可以作为一个弹出菜单控件
 
(1)简单尝试直接在窗口上添加一个UIImageView
HVWHomeViewController:
复制代码
 1 /** 标题栏按钮点击事件 */ 2 - (void) titleButtonClickd:(UIButton *) button { 3     self.titleButtonExtended = !self.titleButtonExtended; 4     5     if (self.isTitleButtonExtended) { 6         [button setImage:[UIImage imageWithNamed:@"navigationbar_arrow_up"] forState:UIControlStateNormal]; 7         8         // 弹出框 9         UIView *window = [[UIApplication sharedApplication] keyWindow];10         UIImageView *popView = [[UIImageView alloc] init];11         popView.size = CGSizeMake(200, 200);12         popView.centerX = window.width * 0.5;13         popView.y = 55;14         popView.image = [UIImage resizedImage:@"popover_background"];15         [self.navigationController.view addSubview:popView];16        17     } else {18         [button setImage:[UIImage imageWithNamed:@"navigationbar_arrow_down"] forState:UIControlStateNormal];19     }20 }
复制代码
 
Image(77)
 
(2)点击其他区域,隐藏弹出框
使用一个全屏透明/半透明UIButton夹在弹出框和底层的控件之间,监听点击事件
复制代码
 1 /** 标题栏按钮点击事件 */ 2 - (void) titleButtonClickd:(UIButton *) button { 3     self.titleButtonExtended = !self.titleButtonExtended; 4     5     if (self.isTitleButtonExtended) { 6         [button setImage:[UIImage imageWithNamed:@"navigationbar_arrow_up"] forState:UIControlStateNormal]; 7         8         UIView *window = [[UIApplication sharedApplication] keyWindow]; 9        10         // 中间辅助覆盖层(帮助隐藏弹出框)11         UIButton *coverLayer = [UIButton buttonWithType:UIButtonTypeCustom];12         coverLayer.frame = window.bounds;13         coverLayer.backgroundColor = [UIColor blackColor];14         coverLayer.alpha = 0.2;15         [window addSubview:coverLayer];16         [coverLayer addTarget:self action:@selector(coverLayerClicked:) forControlEvents:UIControlEventTouchUpInside];17        18         // 弹出框19         UIImageView *popView = [[UIImageView alloc] init];20         self.popView = popView;21         popView.size = CGSizeMake(200, 200);22         popView.centerX = window.width * 0.5;23         popView.y = 55;24         popView.userInteractionEnabled = YES;25        26         popView.image = [UIImage resizedImage:@"popover_background"];27         [window addSubview:popView];28        29     } else {30         [button setImage:[UIImage imageWithNamed:@"navigationbar_arrow_down"] forState:UIControlStateNormal];31     }32 }33 34 /** 辅助覆盖层点击事件 */35 - (void) coverLayerClicked:(UIButton *) button {36     if (self.isTitleButtonExtended) {37         [button removeFromSuperview];38         [self.popView removeFromSuperview];39         [self titleButtonClickd:self.titleButton];40     }41 }
复制代码
 
popView
 
 
(3)由于弹出框功能可能在多处用到,而且让控制器负责创建不合适,所以封装成一个类
封装成“弹出菜单”类HVWPopMenu(继承UIView)
内部包含:
背景图片
遮盖UIButton
一个内容界面 (如tableViewController),作为背景图片的子控件
 
复制代码
 1 // 2 //  HVWPopMenu.h 3 //  HVWWeibo 4 // 5 //  Created by hellovoidworld on 15/2/2. 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved. 7 // 8  9 #import <UIKit/UIKit.h>10 11 typedef enum {12     PopMenuArrowLeft,13     PopMenuArrowMid,14     PopMenuArrowRight15 } PopMenuArrow;16 17 @class HVWPopMenu;18 @protocol HVWPopMenuDelegate <NSObject>19 20 @optional21 - (void) popMenuDidHideMenu:(HVWPopMenu *) popMenu;22 23 @end24 25 @interface HVWPopMenu : UIView26 27 /** 背景兼内容容器 */28 @property(nonatomic, strong) UIImageView *backgroundContainer;29 30 #pragma mark - 成员属性31 /** 遮盖夹层 */32 @property(nonatomic, strong) UIButton *coverLayer;33 34 /** 内容控件 */35 @property(nonatomic, strong) UIView *contentView;36 37 /** 箭头位置 */38 @property(nonatomic, assign) PopMenuArrow popMenuArrow;39 40 /** 遮盖夹层透明标识 */41 @property(nonatomic, assign, getter=isDimCoverLayer) BOOL dimCoverLayer;42 43 /** 代理 */44 @property(nonatomic, weak) id<HVWPopMenuDelegate> delegate;45 46 47 #pragma mark - 初始化方法48 - (instancetype) initWithContentView:(UIView *) contentView;49 + (instancetype) popMenuWithContentView:(UIView *) contentView;50 51 #pragma mark - 使用方法52 /** 弹出 */53 - (void) showMenuInRect:(CGRect) rect;54 55 /** 隐藏 */56 - (void) hideMenu;57 58 59 @end
复制代码
 
复制代码
  1 //  2 //  HVWPopMenu.m  3 //  HVWWeibo  4 //  5 //  Created by hellovoidworld on 15/2/2.  6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.  7 //  8   9 #import "HVWPopMenu.h" 10  11 @implementation HVWPopMenu 12  13 #pragma mark - 初始化方法 14 - (instancetype) initWithContentView:(UIView *) contentView { 15     if (self = [super init]) { 16         self.contentView = contentView; 17     } 18     19     return self; 20 } 21  22 + (instancetype) popMenuWithContentView:(UIView *) contentView { 23     return [[self alloc] initWithContentView:contentView]; 24 } 25  26 /** 初始化子控件 */ 27 - (instancetype)initWithFrame:(CGRect)frame { 28     self = [super initWithFrame:frame]; 29     if (self) { 30         // 中间辅助覆盖层(帮助隐藏弹出框) 31         UIButton *coverLayer = [UIButton buttonWithType:UIButtonTypeCustom]; 32         self.coverLayer = coverLayer; 33         [self setDimCoverLayer:YES]; 34         [coverLayer addTarget:self action:@selector(coverLayerClicked) forControlEvents:UIControlEventTouchUpInside]; 35         [self addSubview:coverLayer]; 36         37         // 添加背景容器 38         UIImageView *backgroundContainer = [[UIImageView alloc] init]; 39         self.backgroundContainer = backgroundContainer; 40         backgroundContainer.userInteractionEnabled = YES; 41         [self setPopMenuArrow:PopMenuArrowMid]; 42         [self addSubview:backgroundContainer]; 43     } 44     45     return self; 46 } 47  48 /** 遮盖夹层点击事件 */ 49 - (void) coverLayerClicked { 50     [self hideMenu]; 51 } 52  53 #pragma mark - 使用方法 54 /** 弹出 */ 55 - (void) showMenuInRect:(CGRect) rect { 56     // 准备添加到当前主窗口上 57     UIView *window = [[UIApplication sharedApplication] keyWindow]; 58     self.frame = window.bounds; 59     [window addSubview:self]; 60     61     self.coverLayer.frame = window.bounds; 62     self.backgroundContainer.frame = rect; 63     64     // 添加内容控件 65     if (self.contentView) { 66         CGFloat topMargin = 12; 67         CGFloat leftMargin = 5; 68         CGFloat bottomMargin = 8; 69         CGFloat rightMargin = 5; 70         71         self.contentView.x = leftMargin; 72         self.contentView.y = topMargin; 73         self.contentView.width = self.backgroundContainer.width - leftMargin - rightMargin; 74         self.contentView.height = self.backgroundContainer.height - topMargin - bottomMargin; 75         76         [self.backgroundContainer addSubview:self.contentView]; 77     } 78 } 79  80 /** 隐藏 */ 81 - (void) hideMenu { 82     if ([self.delegate respondsToSelector:@selector(popMenuDidHideMenu:)]) { 83         [self.delegate popMenuDidHideMenu:self]; 84     } 85     86     [self removeFromSuperview]; 87 } 88  89 #pragma mark - 特性设置 90 /** 设置遮盖夹层是否透明 */ 91 - (void)setDimCoverLayer:(BOOL)dimCoverLayer { 92     if (dimCoverLayer) { // 需要半透明模糊效果的 93         self.coverLayer.backgroundColor = [UIColor blackColor]; 94         self.coverLayer.alpha = 0.2; 95     } else { // 全透明 96         self.coverLayer.backgroundColor = [UIColor clearColor]; 97         self.coverLayer.alpha = 1.0; 98     } 99 }100 101 102 /** 设置弹出菜单顶部箭头位置:左、中、右 */103 - (void)setPopMenuArrow:(PopMenuArrow)popMenuArrow {104     _popMenuArrow = popMenuArrow;105    106     switch (popMenuArrow) {107         case PopMenuArrowLeft:108             self.backgroundContainer.image = [UIImage resizedImage:@"popover_background_left"];109             break;110         case PopMenuArrowMid:111             self.backgroundContainer.image = [UIImage resizedImage:@"popover_background"];112             break;113         case PopMenuArrowRight:114             self.backgroundContainer.image = [UIImage resizedImage:@"popover_background_right"];115             break;116         default:117             break;118     }119 }120 121 @end
复制代码
 
复制代码
 1 //  HVWHomeViewController.m 2 /** 标题栏按钮点击事件 */ 3 - (void) titleButtonClickd:(UIButton *) button { 4     self.titleButtonExtended = !self.titleButtonExtended; 5     6     if (self.isTitleButtonExtended) { 7         [button setImage:[UIImage imageWithNamed:@"navigationbar_arrow_up"] forState:UIControlStateNormal]; 8         9         // 添加弹出菜单10         UITableView *tableView = [[UITableView alloc] init];11         HVWPopMenu *popMenu = [HVWPopMenu popMenuWithContentView:tableView];12         popMenu.delegate = self;13         popMenu.dimCoverLayer = YES; // 模糊遮盖14         popMenu.popMenuArrow = PopMenuArrowMid; // 中部箭头15        16         // 弹出17         [popMenu showMenuInRect:CGRectMake(50, 55, 200, 300)];18        19     } else {20         [button setImage:[UIImage imageWithNamed:@"navigationbar_arrow_down"] forState:UIControlStateNormal];21     }22 }23 24 #pragma mark - HVWPopMenuDelegate25 - (void)popMenuDidHideMenu:(HVWPopMenu *)popMenu {26     UIButton *titleButton = (UIButton *)self.navigationItem.titleView;27     [self titleButtonClickd:titleButton];28 }
复制代码
0 0