You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

393 lines
15 KiB

//
// LMJDropdownMenu.m
//
// Created by JerryLMJ on 15/5/4.
// Copyright (c) 2015LMJ. All rights reserved.
//
#import "LMJDropdownMenu.h"
@interface LMJDropdownMenu() <UITableViewDelegate, UITableViewDataSource, 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 LMJDropdownMenu
{
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
- (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];
_optionFont = [UIFont systemFontOfSize:13];
_optionTextColor = [UIColor blackColor];
_optionTextAlignment = NSTextAlignmentCenter;
_optionTextMarginLeft = 15;
_optionNumberOfLines = 0;
_optionIconSize = CGSizeMake(0, 0);
_optionIconMarginRight = 15;
_optionLineColor = [UIColor whiteColor];
_optionLineHeight = 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];
// call 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 {
// UIApplication * application = [UIApplication sharedApplication];
// if (application && application.windows && application.windows.count > 0) {
// return application.windows.lastObject;
// }
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.optionFont;
titleLabel.textColor = self.optionTextColor;
titleLabel.numberOfLines = self.optionNumberOfLines;
titleLabel.textAlignment = self.optionTextAlignment;
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, self.frame.size.width, self.optionLineHeight)];
line.backgroundColor = self.optionLineColor;
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(self.optionTextMarginLeft, 0, self.frame.size.width - self.optionTextMarginLeft -self.optionIconSize.width -self.optionIconMarginRight, 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.optionIconSize.width -self.optionIconMarginRight, (cHeight - self.optionIconSize.height)/2, self.optionIconSize.width, self.optionIconSize.height);
UIView *line = [cell viewWithTag:777];
line.frame = CGRectMake(0, 0, self.frame.size.width, self.optionLineHeight);
line.backgroundColor = self.optionLineColor;
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)setRotateIcon:(UIImage *)rotateIcon {
_rotateIcon = rotateIcon;
[self.arrowMark setImage:rotateIcon];
}
- (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)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)setTitleEdgeInsets:(UIEdgeInsets)titleEdgeInsets{
_titleEdgeInsets = titleEdgeInsets;
self.mainBtn.titleEdgeInsets = titleEdgeInsets;
}
- (void)setShowsVerticalScrollIndicatorOfOptionsList:(BOOL)showsVerticalScrollIndicatorOfOptionsList {
_optionsList.showsVerticalScrollIndicator = showsVerticalScrollIndicatorOfOptionsList;
}
@end