转载请标明出处:http://blog.csdn.net/android_ls/article/details/45877983
声明:仿新浪微博项目,所用所有图片资源都来源于官方新浪微博IOS客户端,编写本应用的目的在于学习交流,如涉及侵权请告知,我会及时换掉用到的相关图片。
接着上一篇博文,这篇我们来聊聊新浪微博导航栏上,点击中间部分的标题(titleView)弹出的下拉菜单是如何实现。
1、自定义导航栏中间的titleView,代码如下:
  // 设置导航栏中间的titleView
    _titleButton = [self titleViewWithNickname:@"指间有梦"];
    self.navigationItem.titleView = _titleButton;#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;
}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];
}@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];
    
    // 调用根据搜索条件返回相应的微博数据
    // ...
}
点击屏幕中除下拉菜单外的任意地方,或者点击下拉菜单中的某一项(比如点击了“好友圈”),让下拉菜单销毁。
再次点击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
//  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
// // 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
原文:http://blog.csdn.net/android_ls/article/details/45877983