仿新浪微博IOS客户端(v5.2.8)——下拉菜单栏的实现
转载请标明出处:http://blog.csdn.net/android_ls/article/details/45877983
声明:仿新浪微博项目,所用所有图片资源都来源于官方新浪微博IOS客户端,编写本应用的目的在于学习交流,如涉及侵权请告知,我会及时换掉用到的相关图片。
接着上一篇博文,这篇我们来聊聊新浪微博导航栏上,点击中间部分的标题(titleView)弹出的下拉菜单是如何实现。
1、自定义导航栏中间的titleView,代码如下:
// 设置导航栏中间的titleView _titleButton = [self titleViewWithNickname:@"指间有梦"]; self.navigationItem.titleView = _titleButton;
2、在UIButton中默认有imageView和titleLabel两个子View,默认imageView是在左边的,而titleLabel是在右边的。我们看到在新浪微博首页上,titleView上显示的是titleLabel在左边,imageView在titleView的右边,我们试着调整UIButton中子View的显示位置,具体实现代码如下:
#pragma mark 设置导航栏中间的titleView -(UIButton *) titleViewWithNickname:(NSString *)nickname { UIButton *titleButton = [[UIButton alloc] init]; // 设置图片和文字 [titleButton setTitle:nickname forState:UIControlStateNormal]; [titleButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; titleButton.titleLabel.font = [UIFont systemFontOfSize:18]; [titleButton setImage:[UIImage imageNamed:@"navigationbar_arrow_down"] forState:UIControlStateNormal]; [titleButton setImage:[UIImage imageNamed:@"navigationbar_arrow_up"] forState:UIControlStateSelected]; // 90 40这两个值目前是随便写的 titleButton.imageEdgeInsets = UIEdgeInsetsMake(0, 90, 0, 0); titleButton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 40); // 130这个值目前是随便写的,后面要改为根据内容自动计算长度 titleButton.size = CGSizeMake(130, 40); // titleButton.backgroundColor = [UIColor redColor]; [titleButton addTarget:self action:@selector(titleClick:) forControlEvents:UIControlEventTouchUpInside]; return titleButton; }
注:不必拘于这种方式,其他方式也是可以实现(比如自定义一个View,往其中添加两个子View)。
3、调整后的效果图如下:
4、点击自定义的titleView,弹出下拉菜单,具体实现代码如下:
#pragma mark 点击导航栏上的标题事件处理器 - (void)titleClick:(UIButton *)titleButton { // 1.创建下拉菜单 DropdownMenuView *dropdownMenuView = [[DropdownMenuView alloc] init]; // 设置下拉菜单弹出、销毁事件的监听者 dropdownMenuView.delegate = self; // 2.设置要显示的内容 TitleMenuViewController *titleMenuVC = [[TitleMenuViewController alloc] init]; titleMenuVC.dropdownMenuView = dropdownMenuView; titleMenuVC.delegate = self; titleMenuVC.view.width = kMobilePhoneScreenWidth/2; titleMenuVC.view.height = kMobilePhoneScreenHeight/2; dropdownMenuView.contentController = titleMenuVC; // 3.显示下拉菜单 [dropdownMenuView showFrom:titleButton]; }
5、让当前控制器实现DropdownMenuDelegate和TitleMenuDelegate协议,实现相应的函数,具体代码如下:
@interface HomeViewController ()<DropdownMenuDelegate, TitleMenuDelegate> { UIButton *_titleButton; } @end
#pragma mark - DropdownMenuDelegate #pragma mark 下拉菜单被销毁了 - (void)dropdownMenuDidDismiss:(DropdownMenuView *)menu { // 让指示箭头向下 UIButton *titleButton = (UIButton *)self.navigationItem.titleView; titleButton.selected = NO; } #pragma mark 下拉菜单显示了 - (void)dropdownMenuDidShow:(DropdownMenuView *)menu { // 让指示箭头向上 UIButton *titleButton = (UIButton *)self.navigationItem.titleView; titleButton.selected = YES; } #pragma mark - TitleMenuDelegate -(void)selectAtIndexPath:(NSIndexPath *)indexPath title:(NSString *)title { MyLog(@"indexPath = %ld", indexPath.row); MyLog(@"当前选择了%@", title); // 修改导航栏的标题 [_titleButton setTitle:title forState:UIControlStateNormal]; // 调用根据搜索条件返回相应的微博数据 // ... }
6、先来看看已实现的效果图,有图有真相。
点击屏幕中除下拉菜单外的任意地方,或者点击下拉菜单中的某一项(比如点击了“好友圈”),让下拉菜单销毁。
再次点击titleView,如下图:
7、下拉菜单实现核心类(DropdownMenuView.h)的源码如下:
// // DropdownMenuView.h // SinaWeibo // // Created by android_ls on 15/5/20. // Copyright (c) 2015年 android_ls. All rights reserved. // // 下拉菜单组件 #import <UIKit/UIKit.h> @class DropdownMenuView; @protocol DropdownMenuDelegate <NSObject> @optional - (void)dropdownMenuDidDismiss:(DropdownMenuView *)menu; - (void)dropdownMenuDidShow:(DropdownMenuView *)menu; @end @interface DropdownMenuView : UIView @property (nonatomic, weak) id<DropdownMenuDelegate> delegate; #pragma mark 在指定UIView下方显示菜单 - (void)showFrom:(UIView *)from; #pragma mark 销毁下拉菜单 - (void)dismiss; // 要显示的内容控制器 @property (nonatomic, strong) UIViewController *contentController; @end
下拉菜单实现核心类(DropdownMenuView.m)的源码如下:
// // DropdownMenuView.m // SinaWeibo // // Created by android_ls on 15/5/20. // Copyright (c) 2015年 android_ls. All rights reserved. // #import "DropdownMenuView.h" @interface DropdownMenuView() { // 用来显示具体内容的容器 UIImageView * _containerView; } @end @implementation DropdownMenuView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // 清除默认的背景颜色 self.backgroundColor = [UIColor clearColor]; // 添加一个灰色图片,作为下拉菜单的背景 _containerView = [[UIImageView alloc] init]; _containerView.image = [UIImage imageNamed:@"popover_background"]; _containerView.userInteractionEnabled = YES; [self addSubview:_containerView]; } return self; } - (void)setContentController:(UIViewController *)contentController { _contentController = contentController; UIView * content = contentController.view; // 调整内容的位置 content.x = 7; content.y = 13; _containerView.height = CGRectGetMaxY(content.frame) + 9; _containerView.width = CGRectGetMaxX(content.frame) + 7; // 添加内容到灰色图片中 [_containerView addSubview:content]; } #pragma mark 在指定UIView下方显示菜单 - (void)showFrom:(UIView *)from { // 1.获得最上面的窗口 UIWindow *window = [[UIApplication sharedApplication].windows lastObject]; // 2.添加自己到窗口上 [window addSubview:self]; // 3.设置尺寸 self.frame = window.bounds; // 4.调整灰色图片的位置 // 默认情况下,frame是以父控件左上角为坐标原点 // 转换坐标系 CGRect newFrame = [from convertRect:from.bounds toView:window]; _containerView.centerX = CGRectGetMidX(newFrame); _containerView.y = CGRectGetMaxY(newFrame); // 通知外界,自己显示了 if ([self.delegate respondsToSelector:@selector(dropdownMenuDidShow:)]) { [self.delegate dropdownMenuDidShow:self]; } } #pragma mark 销毁下拉菜单 - (void)dismiss { [self removeFromSuperview]; // 通知外界,自己被销毁了 if ([self.delegate respondsToSelector:@selector(dropdownMenuDidDismiss:)]) { [self.delegate dropdownMenuDidDismiss:self]; } } #pragma mark 点击自己执行销毁动作 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self dismiss]; } @end
8、TitleMenuViewController.h的源码如下:
// // TitleMenuViewController.h // SinaWeibo // // Created by android_ls on 15/5/20. // Copyright (c) 2015年 android_ls. All rights reserved. // #import <UIKit/UIKit.h> @class DropdownMenuView; @protocol TitleMenuDelegate <NSObject> #pragma mark 当前选中了哪一行 @required - (void)selectAtIndexPath:(NSIndexPath *)indexPath title:(NSString*)title; @end @interface TitleMenuViewController : UITableViewController @property (nonatomic, weak) id<TitleMenuDelegate> delegate; @property (nonatomic, weak) DropdownMenuView * dropdownMenuView; @end
TitleMenuViewController.m的源码如下:
// // TitleMenuViewController.m // SinaWeibo // // Created by android_ls on 15/5/20. // Copyright (c) 2015年 android_ls. All rights reserved. // #import "TitleMenuViewController.h" #import "DropdownMenuView.h" @interface TitleMenuViewController () @property (nonatomic, strong) NSMutableArray * data; @end @implementation TitleMenuViewController - (void)viewDidLoad { [super viewDidLoad]; _data = [NSMutableArray array]; [_data addObject:@"首页"]; [_data addObject:@"好友圈"]; [_data addObject:@"群微博"]; [_data addObject:@"我的微博"]; [_data addObject:@"特别关注"]; [_data addObject:@"名人明星"]; [_data addObject:@"同事"]; [_data addObject:@"同学"]; [self.tableView reloadData]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _data.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ID = @"statusCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } NSString * name = _data[indexPath.row]; cell.textLabel.text = name; return cell; } #pragma mark Cell点击事件处理器 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; if (_dropdownMenuView) { [_dropdownMenuView dismiss]; } if (_delegate) { [_delegate selectAtIndexPath:indexPath title:_data[indexPath.row]]; } } @end
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。