[iOS微博项目 - 1.5] - NavigationBar标题按钮

A.NavigationBar标题按钮

1.需求

  • 在“首页”的导航栏中部设置一个“首页”文字+箭头按钮
  • 统一设置样式
  • 根据实际文本长度调整宽度
  • 消除系统自带的点击高亮效果
  • 点击按钮,箭头上下颠倒

github: https://github.com/hellovoidworld/HVWWeibo

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 HVWNavigationBarTitleButton
12
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 *)titleButton
39 {
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     }else
46     {
47         //换成箭头向下
48         [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal];
49     }
50 }

B.导航栏标题按钮弹出框

1.需求

点击导航栏标题按钮弹出一个框

点击框外的其他地方,隐藏此框

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 }

(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 }

(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     PopMenuArrowRight
15 } PopMenuArrow;
16
17 @class HVWPopMenu;
18 @protocol HVWPopMenuDelegate <NSObject>
19
20 @optional
21 - (void) popMenuDidHideMenu:(HVWPopMenu *) popMenu;
22
23 @end
24
25 @interface HVWPopMenu : UIView
26
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 - HVWPopMenuDelegate
25 - (void)popMenuDidHideMenu:(HVWPopMenu *)popMenu {
26     UIButton *titleButton = (UIButton *)self.navigationItem.titleView;
27     [self titleButtonClickd:titleButton];
28 }
时间: 2024-10-02 02:08:21

[iOS微博项目 - 1.5] - NavigationBar标题按钮的相关文章

[iOS微博项目 - 3.4] - 获取用户信息

github: https://github.com/hellovoidworld/HVWWeibo   A.获取用户信息 1.需求 获取用户信息并储存 把用户昵称显示在“首页”界面导航栏的标题上 2.思路 使用微博API 将用户信息封装到HVWUser模型中 把获取的用户名存放到账户信息HVWAccountInfo模型中存储到沙盒 3.实现 1 // HVWHomeViewController.m 2 /** 获取用户信息 */ 3 - (void) setupUserInfo { 4 //

[iOS微博项目 - 3.1] - 发微博界面

github: https://github.com/hellovoidworld/HVWWeibo   A.发微博界面:自定义UITextView 1.需求 用UITextView做一个编写微博的输入框 没有输入任何文本的时候显示占位文本 统一占位文本和正文的字体 2.思路 系统自带的输入控件有UITextField和UITextView两种 UITextField:自带占位文本属性,不能换行 UITextView:没有占位文本属性,能换行 这里我们选择UITextView进行改造 根据是否输

[iOS微博项目 - 1.4] - 各种item NavigationBar &amp; NavigationItem &amp; BarButtonItem || TabBar &amp; TabBarItem

一.UINavigationItem1> 获得方式self.navigationItem // self是指控制器 2> 作用可以用来设置当前控制器顶部导航栏的内容// 设置导航栏中间的内容self.navigationItem.titleself.navigationItem.titleView 二.UIBarButtonItem1> 用在什么地方// 设置导航栏左上角的内容self.navigationItem.leftBarButtonItem// 设置导航栏右上角的内容self.

[iOS微博项目 - 1.0] - 搭建基本框架

A.搭建基本环境 github: https://github.com/hellovoidworld/HVWWeibo 项目结构: 1.使用代码构建UI,不使用storyboard AppDelegate: 1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 2 // Override point for customiza

[iOS微博项目 - 3.6] - 获取未读消息

github: https://github.com/hellovoidworld/HVWWeibo   A.获取登陆用户未读消息 1.需求 获取所有未读消息,包括新微博.私信.@.转发.关注等 把未读消息数显示在相应的tabItem上 把总的未读消息数显示在app图标上 当app进入后台,仍然需要刷新未读消息数量数据 读取了未读消息之后清空计数 监听tabBarItem的点击,刷新数据(例如重复点击"首页"要刷新微博) 2.思路 使用微博提醒API获取未读消息 使用定时器定时获取 在

蓝懿IOS微博项目实现登录

登录流程: 首次登录进入登录页面,根据借口借口文档网路请求,返回数据里有code,截取返回数据取到code,之后再次访问,请求返回token,token是我们最后想要的,以后的发微博等操作都要用token.第一次登入后,下次启动程序点击登录按钮不会再登录,因为第一次登录时候已经把获取的token拿到并用plist文件存. 各种初始化方法何时执行: 1.init     一般用于模型层的对象初始化时使用 2.initWithframe  纯代码创建控件 3.initWithCoder 通过xib或

iOS微博项目(七)发微博和定位

class a导入class b,class b导入class a 会出现错误 如果keyboard不显示,应该是hardware->connect选择了 1. 发微博UI 2.定位 一直不回调,后来发现是ios8后方法更新了:http://blog.devzeng.com/blog/ios8-corelocation-framework.html 1)[_locationManager requestAlwaysAuthorization];//添加这句2)在Info.plist文件中添加如下

[iOS微博项目 - 3.0] - 手动刷新微博

github: https://github.com/hellovoidworld/HVWWeibo A.下拉刷新微博 1.需求 在“首页”界面,下拉到一定距离的时候刷新微博数据 刷新数据的时候使用控件提示 新数据要加在旧数据的前面 刷新完毕隐藏刷新控件 刷新数据完毕,导航栏下方弹出一个提示框,提示刷新微博数量 2.思路 直接使用系统自带的UIRefreshControl就可以做出动画效果 使用微博的获取微博API参数since_id可以控制加载的微博从哪个id开始 使用可变数组来拼接新旧微博数

[iOS微博项目 - 4.0] - 自定义微博cell

github: https://github.com/hellovoidworld/HVWWeibo A.自定义微博cell基本结构 1.需求 创建自定义cell的雏形 cell包含:内容.工具条 内容包含:原创内容.转发内容 2.思路 使用分层控件,逐层实现 分离model和view model:数据模型.frame模型 view:就是控件本身 frame模型:包含数据模型和子控件frame 根据数据模型来决定子控件是否显示(例如转发内容) cell的view设计雏形: 控件的成员属性层次: