看了很多的demo,看到思路大致相同。手动模仿写一个。
DropdownMenu.h
#import <UIKit/UIKit.h>
@class DropdownMenu;
@protocol LHDropdownMenuDelegate <NSObject>
@optional
// 当选择某个选项时调用
- (void)dropdownMenu:(DropdownMenu *)menu didSelectOptionAtIndex:(NSUInteger)index optionTitle:(NSString *)title;
// 当下拉菜单将要显示时调用
- (void)dropdownMenuWillShow:(DropdownMenu *)menu;
// 当下拉菜单已经显示时调用
- (void)dropdownMenuDidShow:(DropdownMenu *)menu;
// 当下拉菜单将要收起时调用
- (void)dropdownMenuWillHidden:(DropdownMenu *)menu;
// 当下拉菜单已经收起时调用
- (void)dropdownMenuDidHidden:(DropdownMenu *)menu;
@end
@protocol DropdownMenuDataSource <NSObject>
@required
/*
list的内容代理
*/
- (NSUInteger)numberOfOptionsInDropdownMenu:(DropdownMenu *)menu;
- (CGFloat)dropdownMenu:(DropdownMenu *)menu heightForOptionAtIndex:(NSUInteger)index;
- (NSString *)dropdownMenu:(DropdownMenu *)menu titleForOptionAtIndex:(NSUInteger)index;
@optional
- (UIImage *)dropdownMenu:(DropdownMenu *)menu iconForOptionAtIndex:(NSUInteger)index;
@end
@interface DropdownMenu : UIView<UITableViewDataSource,UITableViewDelegate>
@property (nonatomic, weak) id <DropdownMenuDataSource> dataSource;
@property (nonatomic, weak) id <LHDropdownMenuDelegate> delegate;
/*
Menu标题
*/
//标题
@property (nonatomic,copy) NSString * title;
//背景色
@property (nonatomic,strong) UIColor * titleBgColor;
//字体大小
@property (nonatomic,strong) UIFont * titleFont;
//字体颜色
@property (nonatomic,strong) UIColor * titleColor;
//文本的Alignment
@property (nonatomic) NSTextAlignment titleAlignment;
@property (nonatomic) UIEdgeInsets titleEdgeInsets;
//图标
@property (nonatomic,strong) UIImage * rotateIcon;
//图标大小
@property (nonatomic,assign) CGSize rotateIconSize;
//
@property (nonatomic,assign) CGFloat rotateIconMarginRight; // default: 7.5
//图标的颜色
@property (nonatomic,strong) UIColor * rotateIconTint;
/*
-------list
*/
//列表的颜色
@property (nonatomic,strong) UIColor * optionBgColor;
//列表文本的大小
@property (nonatomic,strong) UIFont * listOptionFont;
//列表文本的颜色
@property (nonatomic,strong) UIColor * listOptionTextColor;
//列表文本的Alignment
@property (nonatomic) NSTextAlignment listOptionTextAlignment;
//列表文本的每行显示
@property (nonatomic) NSInteger listOptionNumberOfLines;
//列表的图标 default:(15,15)
@property (nonatomic,assign) CGSize listOptionIconSize;
//列表图标右边距 default: 15
@property (nonatomic,assign) CGFloat listOptionIconMarginRight;
//列表分割线的显色 default: white
@property (nonatomic,strong) UIColor * listOptionLineColor;
//列表分割线导读 default: 0.5
@property (nonatomic,assign) CGFloat listOptionLineHeight;
/*
选项列表的最大高度。超出最大高度后,选项可滚动 (optionsListLimitHeight <= 0 时,下拉列表将显示所有选项)
*/
@property (nonatomic,assign) CGFloat optionsListLimitHeight; // default: 0
@property (nonatomic,assign) BOOL showsVerticalScrollIndicatorOfOptionsList; // default: YES
// 下拉动画时间 default: 0.25
@property (nonatomic,assign) CGFloat animateTime;
- (void)reloadOptionsData;
- (void)showDropDown; // 下拉菜单显示
- (void)hideDropDown; // 下拉菜单隐藏
@end
DropdownMenu.m
#import "DropdownMenu.h"
@interface DropdownMenu() <UIGestureRecognizerDelegate>
@property (nonatomic, strong) UIButton *mainBtn; // 菜单按钮
@property (nonatomic, strong) UIImageView * arrowMark; // 尖头图标
@property (nonatomic, strong) UITableView *optionsList; // 下拉列表
@property (nonatomic, strong) UIView *floatView;
@property (nonatomic, strong) UIView *coverView;
@end
@implementation DropdownMenu
{
BOOL _isOpened;
}
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self initProperties];
[self initViews];
[self initFrame:self.frame];
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self initProperties];
[self initViews];
[self initFrame:self.frame];
}
- (void)layoutSubviews {
if (_isOpened) return;
CGFloat width = self.frame.size.width;
CGFloat height = self.frame.size.height;
[_floatView setFrame:CGRectMake(_floatView.frame.origin.x, _floatView.frame.origin.y, width, height)];
[_mainBtn setFrame:CGRectMake(0, 0, width, height)];
[_arrowMark setFrame:CGRectMake(width -self.rotateIconMarginRight -self.rotateIconSize.width, (height -self.rotateIconSize.height)/2, self.rotateIconSize.width, self.rotateIconSize.height)];
[_optionsList setFrame:CGRectMake(0, height, width, _optionsList.frame.size.height)];
}
#pragma mark - Init ,default默认
- (void)initProperties{
_title = @"Please Select";
_titleBgColor = [UIColor colorWithRed:64/255.f green:151/255.f blue:255/255.f alpha:1];
_titleFont = [UIFont boldSystemFontOfSize:15];
_titleColor = [UIColor whiteColor];
_titleAlignment = NSTextAlignmentLeft;
_titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 10);
_rotateIcon = nil;
_rotateIconSize = CGSizeMake(15, 15);
_rotateIconMarginRight = 7.5;
_rotateIconTint = [UIColor blackColor];
_optionBgColor = [UIColor colorWithRed:64/255.f green:151/255.f blue:255/255.f alpha:0.5];
_listOptionFont = [UIFont systemFontOfSize:13];
_listOptionTextColor = [UIColor blackColor];
_listOptionTextAlignment = NSTextAlignmentCenter;
_listOptionNumberOfLines = 0;
_listOptionIconSize = CGSizeMake(0, 0);
_listOptionIconMarginRight = 15;
_listOptionLineColor = [UIColor whiteColor];
_listOptionLineHeight = 0.5f;
_animateTime = 0.25f;
_optionsListLimitHeight = 0;
_isOpened = NO;
}
- (void)initViews{
self.layer.masksToBounds = YES;
_floatView = [[UIView alloc] initWithFrame:self.bounds];
_floatView.layer.masksToBounds = YES;
[self addSubview:_floatView];
// 主按钮 显示在界面上的点击按钮
_mainBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_mainBtn addTarget:self action:@selector(clickMainBtn:) forControlEvents:UIControlEventTouchUpInside];
_mainBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
_mainBtn.titleEdgeInsets = UIEdgeInsetsMake(0, 15, 0, 0);
_mainBtn.selected = NO;
[_floatView addSubview:_mainBtn];
// 旋转尖头
_arrowMark = [[UIImageView alloc] init];
[_arrowMark setTintColor:self.rotateIconTint];
[_mainBtn addSubview:_arrowMark];
// 下拉列表TableView
_optionsList = [[UITableView alloc] init];
_optionsList.delegate = self;
_optionsList.dataSource = self;
_optionsList.separatorStyle = UITableViewCellSeparatorStyleNone;
_optionsList.scrollEnabled = NO;
[_floatView addSubview:_optionsList];
}
- (void)initFrame:(CGRect)frame {
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;
[_floatView setFrame:CGRectMake(0, 0, width, height)];
[_mainBtn setFrame:CGRectMake(0, 0, width, height)];
[_arrowMark setFrame:CGRectMake(width -self.rotateIconMarginRight -self.rotateIconSize.width, (height -self.rotateIconSize.height)/2, self.rotateIconSize.width, self.rotateIconSize.height)];
[_optionsList setFrame:CGRectMake(0, height, width, _optionsList.frame.size.height)];
}
#pragma mark - Action Methods
- (void)reloadOptionsData{
[self.optionsList reloadData];
}
- (void)clickMainBtn:(UIButton *)button{
if(button.selected == NO) {
[self showDropDown];
}else {
[self hideDropDown];
}
}
- (void)showDropDown{ /* 显示下拉列表 */
_isOpened = YES;
// 变更menu图层
CGPoint newPosition = [self getScreenPosition];
_floatView.frame = CGRectMake(newPosition.x, newPosition.y, _floatView.bounds.size.width, _floatView.bounds.size.height);
_floatView.layer.borderColor = self.layer.borderColor;
_floatView.layer.borderWidth = self.layer.borderWidth;
_floatView.layer.cornerRadius = self.layer.cornerRadius;
[self.coverView addSubview:_floatView];
// cell delegate
if ([self.delegate respondsToSelector:@selector(dropdownMenuWillShow:)]) {
[self.delegate dropdownMenuWillShow:self]; // 将要显示回调代理
}
// 刷新下拉列表数据
[self reloadOptionsData];
// 菜单高度计算
CGFloat listHeight = 0;
if (self.optionsListLimitHeight <= 0) { // 当未设置下拉菜单最小展示高度
NSUInteger count = [self.dataSource numberOfOptionsInDropdownMenu:self];
for (int i = 0; i < count; i++) {
CGFloat cHeight = [self.dataSource dropdownMenu:self heightForOptionAtIndex:i];
listHeight += cHeight;
}
_optionsList.scrollEnabled = NO;
} else {
listHeight = self.optionsListLimitHeight;
_optionsList.scrollEnabled = YES;
}
// 执行展开动画
__weak typeof(self) weakSelf = self;
[UIView animateWithDuration:self.animateTime animations:^{
UIView *floatView = weakSelf.floatView;
UIButton *mainBtn = weakSelf.mainBtn;
UITableView *listView = weakSelf.optionsList;
floatView.frame = CGRectMake(floatView.frame.origin.x, floatView.frame.origin.y, floatView.frame.size.width, mainBtn.frame.size.height + listHeight);
weakSelf.arrowMark.transform = CGAffineTransformMakeRotation(M_PI);
listView.frame = CGRectMake(listView.frame.origin.x, listView.frame.origin.y, listView.frame.size.width, listHeight);
}completion:^(BOOL finished) {
if ([self.delegate respondsToSelector:@selector(dropdownMenuDidShow:)]) {
[self.delegate dropdownMenuDidShow:self]; // 已经显示回调代理
}
}];
_mainBtn.selected = YES;
}
- (void)hideDropDown{ // 隐藏下拉列表
// call delegate
if ([self.delegate respondsToSelector:@selector(dropdownMenuWillHidden:)]) {
[self.delegate dropdownMenuWillHidden:self]; // 将要隐藏回调代理
}
// 执行关闭动画
__weak typeof(self) weakSelf = self;
[UIView animateWithDuration:self.animateTime animations:^{
UIView *floatView = weakSelf.floatView;
UIButton *mainBtn = weakSelf.mainBtn;
weakSelf.arrowMark.transform = CGAffineTransformIdentity;
weakSelf.floatView.frame = CGRectMake(floatView.frame.origin.x, floatView.frame.origin.y, floatView.frame.size.width, mainBtn.frame.size.height);
}completion:^(BOOL finished) {
weakSelf.optionsList.frame = CGRectMake(weakSelf.optionsList.frame.origin.x, weakSelf.optionsList.frame.origin.y, weakSelf.frame.size.width, 0);
// 变更menu图层
weakSelf.floatView.frame = weakSelf.floatView.bounds;
[self addSubview:weakSelf.floatView];
[weakSelf.coverView removeFromSuperview];
weakSelf.coverView = nil;
self->_isOpened = NO;
if ([self.delegate respondsToSelector:@selector(dropdownMenuDidHidden:)]) {
[self.delegate dropdownMenuDidHidden:self]; // 已经隐藏回调代理
}
}];
_mainBtn.selected = NO;
}
#pragma mark - Utility Methods
- (CGPoint)getScreenPosition {
return [self.superview convertPoint:self.frame.origin toView:[self getCurrentKeyWindow]];
}
- (UIWindow *)getCurrentKeyWindow {
return [UIApplication sharedApplication].keyWindow;
}
#pragma mark - UITableView Delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.dataSource numberOfOptionsInDropdownMenu:self];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self.dataSource dropdownMenu:self heightForOptionAtIndex:indexPath.row];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"MenuOptionListCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
//---------------------------下拉选项样式,可在此处自定义-------------------------
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = self.optionBgColor;
UILabel * titleLabel = [[UILabel alloc] init];
titleLabel.font = self.listOptionFont;
titleLabel.textColor = self.listOptionTextColor;
titleLabel.numberOfLines = self.listOptionNumberOfLines;
titleLabel.textAlignment = self.listOptionTextAlignment;
titleLabel.tag = 999;
[cell addSubview:titleLabel];
UIImageView * icon = [[UIImageView alloc] init];
icon.tag = 888;
[cell addSubview:icon];
UIView * line = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, self.listOptionLineHeight)];
line.backgroundColor = self.listOptionLineColor;
line.tag = 777;
[cell addSubview:line];
}
CGFloat cHeight = [self.dataSource dropdownMenu:self heightForOptionAtIndex:indexPath.row];
UILabel * titleLabel = [cell viewWithTag:999];
titleLabel.text = [self.dataSource dropdownMenu:self titleForOptionAtIndex:indexPath.row];;
titleLabel.frame = CGRectMake(15, 0, self.frame.size.width - 15 -self.listOptionIconSize.width -self.listOptionIconMarginRight, cHeight);
UIImageView * icon = [cell viewWithTag:888];
if ([self.dataSource respondsToSelector:@selector(dropdownMenu:iconForOptionAtIndex:)]){
icon.image = [self.dataSource dropdownMenu:self iconForOptionAtIndex:indexPath.row];
}
icon.frame = CGRectMake(self.frame.size.width -self.listOptionIconSize.width -self.listOptionIconMarginRight, (cHeight - self.listOptionIconSize.height)/2, self.listOptionIconSize.width, self.listOptionIconSize.height);
UIView *line = [cell viewWithTag:777];
line.frame = CGRectMake(0, 0, cell.frame.size.width, self.listOptionLineHeight);
line.backgroundColor = self.listOptionLineColor;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UILabel * titleLabel = [cell viewWithTag:999];
self.title = titleLabel.text;
if ([self.delegate respondsToSelector:@selector(dropdownMenu:didSelectOptionAtIndex:optionTitle:)]) {
[self.delegate dropdownMenu:self didSelectOptionAtIndex:indexPath.row optionTitle:titleLabel.text];
}
[self hideDropDown];
}
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([NSStringFromClass([touch.view class]) isEqualToString:@"UITableViewCellContentView"]) {
return NO;
}
return YES;
}
#pragma mark - Get Methods
- (BOOL)showsVerticalScrollIndicatorOfOptionsList {
return _optionsList.showsVerticalScrollIndicator;
}
- (UIView *)coverView {
UIWindow *window = [self getCurrentKeyWindow];
if (_coverView == nil) {
_coverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, window.bounds.size.width, window.bounds.size.height)];
_coverView.backgroundColor = [UIColor clearColor];
[window addSubview:_coverView];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideDropDown)];
tap.delegate = self;
[_coverView addGestureRecognizer:tap];
}
return _coverView;
}
#pragma mark - Set Methods
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
[self initFrame:frame];
}
- (void)setRotateIconSize:(CGSize)rotateIconSize {
_rotateIconSize = rotateIconSize;
[self.arrowMark setFrame:CGRectMake(self.mainBtn.bounds.size.width -self.rotateIconMarginRight -rotateIconSize.width, (self.mainBtn.bounds.size.height -rotateIconSize.height)/2, rotateIconSize.width, rotateIconSize.height)];
}
- (void)setRotateIcon:(UIImage *)rotateIcon {
_rotateIcon = rotateIcon;
[self.arrowMark setImage:rotateIcon];
}
- (void)setRotateIconMarginRight:(CGFloat)rotateIconMarginRight {
_rotateIconMarginRight = rotateIconMarginRight;
[self.arrowMark setFrame:CGRectMake(self.mainBtn.bounds.size.width -rotateIconMarginRight -self.rotateIconSize.width, (self.mainBtn.bounds.size.height -self.rotateIconSize.height)/2, self.rotateIconSize.width, self.rotateIconSize.height)];
}
- (void)setRotateIconTint:(UIColor *)rotateIconTint {
_rotateIconTint = rotateIconTint;
self.arrowMark.tintColor = rotateIconTint;
}
- (void)setTitle:(NSString *)title{
_title = title;
[self.mainBtn setTitle:title forState:UIControlStateNormal];
}
- (void)setTitleBgColor:(UIColor *)titleBgColor{
_titleBgColor = titleBgColor;
[self.mainBtn setBackgroundColor:titleBgColor];
[self.arrowMark setBackgroundColor:titleBgColor];
}
- (void)setTitleFont:(UIFont *)titleFont{
_titleFont = titleFont;
self.mainBtn.titleLabel.font = titleFont;
}
- (void)setTitleColor:(UIColor *)titleColor{
_titleColor = titleColor;
[self.mainBtn setTitleColor:titleColor forState:UIControlStateNormal];
}
- (void)setTitleAlignment:(NSTextAlignment)titleAlignment{
_titleAlignment = titleAlignment;
if (titleAlignment == NSTextAlignmentLeft) {
self.mainBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
} else if (titleAlignment == NSTextAlignmentCenter) {
self.mainBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
} else if (titleAlignment == NSTextAlignmentRight) {
self.mainBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
}
}
- (void)setShowsVerticalScrollIndicatorOfOptionsList:(BOOL)showsVerticalScrollIndicatorOfOptionsList {
_optionsList.showsVerticalScrollIndicator = showsVerticalScrollIndicatorOfOptionsList;
}
- (void)setTitleEdgeInsets:(UIEdgeInsets)titleEdgeInsets{
_titleEdgeInsets = titleEdgeInsets;
self.mainBtn.titleEdgeInsets = titleEdgeInsets;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end
在需要的文件里添加并遵循代理<DropdownMenuDataSource,LHDropdownMenuDelegate>
/*
创建菜单数组及设置
*/
- (void)viewDidLoad
{
_menu1OptionTitles = @[@"Option1",@"Option2",@"Option3",@"Option4",@"Option5"];
menu1 = [[DropdownMenu alloc] init];
[menu1 setFrame:CGRectMake(20, 120, 100, 30)];
menu1.dataSource = self;
menu1.delegate = self;
menu1.title = @"Please";
menu1.titleBgColor = [UIColor colorWithRed:64/255.f green:151/255.f blue:255/255.f alpha:1];
[self.view addSubview:menu1];
}
#pragma mark - DropdownMenu DataSource
- (NSUInteger)numberOfOptionsInDropdownMenu:(DropdownMenu *)menu{
return _menu1OptionTitles.count;
}
- (CGFloat)dropdownMenu:(DropdownMenu *)menu heightForOptionAtIndex:(NSUInteger)index{
return 30;
}
- (NSString *)dropdownMenu:(DropdownMenu *)menu titleForOptionAtIndex:(NSUInteger)index{
return _menu1OptionTitles[index];
}
- (UIImage *)dropdownMenu:(DropdownMenu *)menu iconForOptionAtIndex:(NSUInteger)index{
return [UIImage imageNamed:_menu1OptionTitles[index]];
}
#pragma mark - LMJDropdownMenu Delegate
- (void)dropdownMenu:(DropdownMenu *)menu didSelectOptionAtIndex:(NSUInteger)index optionTitle:(NSString *)title{
NSLog(@"你选择了(you selected):menu1,index: %ld - title: %@", index, title);
}
- (void)dropdownMenuWillShow:(DropdownMenu *)menu{
NSLog(@"--将要显示");
}
- (void)dropdownMenuDidShow:(DropdownMenu *)menu{
NSLog(@"--已经显示");
}
- (void)dropdownMenuWillHidden:(DropdownMenu *)menu{
NSLog(@"--将要隐藏");
}
- (void)dropdownMenuDidHidden:(DropdownMenu *)menu{
NSLog(@"--已经隐藏");
}