iOS开发之下拉抽屉效果(DropDownView)

@class DropDownView;

#define SECTION_BTN_TAG_BEGIN   1000
#define SECTION_IV_TAG_BEGIN    3000

@protocol DropDownViewDelegate <NSObject>

@optional

/**
 *  点击触发事件
 *  @param indexPath    被点击的分区及行
 */
- (void)dropDownView:(DropDownView *)dropDownView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
@end


@protocol DropDownViewDataSource <NSObject>

@required
/**
 *  当前分区中的行数
 *  @param section      分区
 *
 *  @return 行数
 */
- (NSInteger)dropDownView:(DropDownView *)dropDownView numberOfRowsInSection:(NSInteger)section;

/**
 *  当前分区的每行的标题
 *  @param indexPath    分区
 *
 *  @return 每行的标题
 */
- (NSString *)dropDownView:(DropDownView *)dropDownView titleForRowAtIndexPath:(NSIndexPath *)indexPath;

/**
 *  默认选中的行
 *
 *  @param row 行数
 *
 *  @return 默认选中的行数
 */
- (NSInteger)defaultShowRow:(NSInteger)row;

@optional

/**
 *  分区数
 *
 *  @return 分区数
 */
- (NSInteger)numberOfSectionsInDropDownView:(DropDownView *)dropDownView;

@end

@interface DropDownView : UIView <UITableViewDelegate,UITableViewDataSource>

/**
 *  数据源代理
 */
@property (nonatomic, assign) id <DropDownViewDataSource> dataSource;

/**
 *  代理
 */
@property (nonatomic, assign) id <DropDownViewDelegate>   delegate;

/**
 *  分组的宽度
 */
@property (nonatomic, assign) CGFloat sectionWidth;

/**
 *  父视图
 */
@property (nonatomic, strong) UIView *mySuperView;

/**
 *  初始化方法
 *
 *  @param frame      坐标
 *  @param delegate   代理
 *  @param dataSource 数据源代理
 *
 *  @return dropView
 */
- (instancetype)initWithFrame:(CGRect)frame delegate:(id)delegate dataSource:(id)dataSource;
#define DEGREES_TO_RADIANS(angle) ((angle)/180.0 *M_PI)
#define RADIANS_TO_DEGREES(radians) ((radians)*(180.0/M_PI))

@interface DropDownView ()
{
    /**当前展开的section,默认-1,表示没有展开*/
    NSInteger currentExtendSection;
    
    /**当前分数个数*/
    NSInteger sectionNum;
}

/**
 *  根视图
 */
@property (nonatomic, strong) UIView *myBasicView;

/**
 *  显示数据的dropview
 */
@property (nonatomic, strong) UITableView *myTableView;

/**
 *  设置每个分区的标题
 *
 *  @param title   标题
 *  @param section 分区
 */
- (void)setTitle:(NSString *)title inSection:(NSInteger)section;

/**
 *  是否隐藏
 */
- (void)hideExtendedChooseView;

@end

@implementation DropDownView

- (instancetype)initWithFrame:(CGRect)frame delegate:(id)delegate dataSource:(id)dataSource {
    if (self = [super initWithFrame:frame]) {
        //对参数初始化
        self.backgroundColor = [UIColor whiteColor];
        currentExtendSection = -1;
        sectionNum = 0;
        
        self.delegate = delegate;
        self.dataSource = dataSource;
        
        //返回分区个数
        if ([self.dataSource respondsToSelector:@selector(numberOfSectionsInDropDownView:)]) {
            sectionNum = [self.dataSource numberOfSectionsInDropDownView:self];
        }
        if (sectionNum == 0) {
            self = nil;
        }
        
        //初始化默认显示的view
        CGFloat sectionWidth = _sectionWidth == 0 ? (1.0*(frame.size.width)/sectionNum) : _sectionWidth;
        for (NSInteger i = 0; i < sectionNum; i++) {
            UIButton *sectionBtn = [[UIButton alloc] initWithFrame:CGRectMake(sectionWidth*i, 1, sectionWidth, frame.size.height-2)];
            sectionBtn.tag = SECTION_BTN_TAG_BEGIN + i;
            [sectionBtn addTarget:self action:@selector(sectionBtnTouch:) forControlEvents:UIControlEventTouchUpInside];
            
            NSString *sectionBtnTitle = @"";
            if ([self.dataSource respondsToSelector:@selector(dropDownView:titleForRowAtIndexPath:)]) {
                //取出对应分区对应行的标题
                sectionBtnTitle = [self.dataSource dropDownView:self titleForRowAtIndexPath:[NSIndexPath indexPathForRow:[self.dataSource defaultShowRow:i] inSection:i]];
            }
            [sectionBtn setTitle:sectionBtnTitle forState:UIControlStateNormal];
            [sectionBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            sectionBtn.titleLabel.font = [UIFont boldSystemFontOfSize:14.0];
            [self addSubview:sectionBtn];
            
            //箭头
            UIImageView *sectionBtnIv = [[UIImageView alloc] initWithFrame:CGRectMake(sectionWidth*i +(sectionWidth - 16), (self.frame.size.height-12)/2, 12, 12)];
            [sectionBtnIv setImage:[UIImage imageNamed:@"down_dark.png"]];
            [sectionBtnIv setContentMode:UIViewContentModeScaleToFill];
            sectionBtnIv.tag = SECTION_IV_TAG_BEGIN + i;
            [self addSubview: sectionBtnIv];
            
            //分隔线
            if (i<sectionNum && i != 0) {
                UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(sectionWidth*i, frame.size.height/4, 1, frame.size.height/2)];
                lineView.backgroundColor = [UIColor blueColor];
                [self addSubview:lineView];
            }
        }
    }
    return self;
}

#pragma mark - 分区被点击
- (void)sectionBtnTouch:(UIButton *)btn {
    NSInteger section = btn.tag - SECTION_BTN_TAG_BEGIN;
    
    UIImageView *currentIV= (UIImageView *)[self viewWithTag:(SECTION_IV_TAG_BEGIN +currentExtendSection)];
    
    [UIView animateWithDuration:0.3 animations:^{
        currentIV.transform = CGAffineTransformRotate(currentIV.transform, DEGREES_TO_RADIANS(180));
    }];
    
    if (currentExtendSection == section) {
        [self hideExtendedChooseView];
    }else{
        currentExtendSection = section;
        currentIV = (UIImageView *)[self viewWithTag:SECTION_IV_TAG_BEGIN + currentExtendSection];
        [UIView animateWithDuration:0.3 animations:^{
            currentIV.transform = CGAffineTransformRotate(currentIV.transform, DEGREES_TO_RADIANS(180));
        }];
        
        [self showChooseListViewInSection:currentExtendSection choosedIndex:[self.dataSource defaultShowRow:currentExtendSection]];
    }
}

- (void)setTitle:(NSString *)title inSection:(NSInteger) section
{
    UIButton *btn = (id)[self viewWithTag:SECTION_BTN_TAG_BEGIN +section];
    [btn setTitle:title forState:UIControlStateNormal];
}

-  (void)hideExtendedChooseView
{
    if (currentExtendSection != -1) {
        currentExtendSection = -1;
        CGRect rect = self.myTableView.frame;
        rect.size.height = 0;
        [UIView animateWithDuration:0.3 animations:^{
            self.myBasicView.alpha = 1.0f;
            self.myTableView.alpha = 1.0f;
            
            self.myBasicView.alpha = 0.2f;
            self.myTableView.alpha = 0.2;
            
            self.myTableView.frame = rect;
        }completion:^(BOOL finished) {
            [self.myTableView removeFromSuperview];
            [self.myBasicView removeFromSuperview];
        }];
    }
}

-(void)showChooseListViewInSection:(NSInteger)section choosedIndex:(NSInteger)index
{
    if (!self.myTableView) {
        self.myBasicView = [[UIView alloc] initWithFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y + self.frame.size.height , self.frame.size.width, self.mySuperView.frame.size.height - self.frame.origin.y - self.frame.size.height)];
        self.myBasicView.backgroundColor = [UIColor yellowColor];
        
        UITapGestureRecognizer *bgTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(bgTappedAction:)];
        [self.myBasicView addGestureRecognizer:bgTap];
        
        self.myTableView = [[UITableView alloc] initWithFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y + self.frame.size.height, self.frame.size.width, 100) style:UITableViewStylePlain];
        self.myTableView.backgroundColor = [UIColor redColor];
        self.myTableView.delegate = self;
        self.myTableView.dataSource = self;
        self.myTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    }
    
    //修改tableview的frame
    int sectionWidth = (self.frame.size.width)/[self.dataSource numberOfSectionsInDropDownView:self];
    CGRect rect = self.myTableView.frame;
    rect.origin.x = sectionWidth *section;
    rect.size.width = sectionWidth;
    rect.size.height = 0;
    self.myTableView.frame = rect;
    [self.mySuperView addSubview:self.myBasicView];
    [self.mySuperView addSubview:self.myTableView];
    
    //动画设置位置
    NSLog(@"%li",[self.dataSource numberOfSectionsInDropDownView:self]);
    rect.size.height = ([self.dataSource dropDownView:self numberOfRowsInSection:currentExtendSection])* 40 + 10;
    [UIView animateWithDuration:0.3 animations:^{
        self.myBasicView.alpha = 0.2;
        self.myTableView.alpha = 0.2;
        
        self.myBasicView.alpha = 1.0;
        self.myTableView.alpha = 1.0;
        self.myTableView.frame =  rect;
    }];
    [self.myTableView reloadData];
}

-(void)bgTappedAction:(UITapGestureRecognizer *)tap
{
    UIImageView *currentIV = (UIImageView *)[self viewWithTag:(SECTION_IV_TAG_BEGIN + currentExtendSection)];
    [UIView animateWithDuration:0.3 animations:^{
        currentIV.transform = CGAffineTransformRotate(currentIV.transform, DEGREES_TO_RADIANS(180));
    }];
    [self hideExtendedChooseView];
}

#pragma mark - UITableViewDelegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([self.delegate respondsToSelector:@selector(dropDownView:didSelectRowAtIndexPath:)]) {
        NSString *chooseCellTitle = [self.dataSource dropDownView:self titleForRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:currentExtendSection]];
        
        UIButton *currentSectionBtn = (UIButton *)[self viewWithTag:SECTION_BTN_TAG_BEGIN + currentExtendSection];
        [currentSectionBtn setTitle:chooseCellTitle forState:UIControlStateNormal];
        
        [self.delegate dropDownView:self didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:currentExtendSection]];
        [self hideExtendedChooseView];
    }
}

#pragma mark - UITableView DataSource

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.dataSource dropDownView:self numberOfRowsInSection:currentExtendSection];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString * cellIdentifier = @"cellIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    
    cell.textLabel.text = [self.dataSource dropDownView:self titleForRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:currentExtendSection]];
    cell.textLabel.font = [UIFont systemFontOfSize:14];
    return cell;
}
@interface ViewController () <DropDownViewDataSource,DropDownViewDelegate>
{
    NSMutableArray *chooseArray;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    chooseArray = [NSMutableArray arrayWithArray:@[
                                                   @[@"童明城1",@"童赟2",@"童林杰3",@"老萧狗4"],
                                                   @[@"童明城1",@"童赟2",@"童林杰3",@"老萧狗4"],
                                                   @[@"童明城1",@"童赟2",@"童林杰3",@"老萧狗4",@"童明城1",@"童赟2",@"童林杰3",@"老萧狗4",@"童明城1",@"童赟2",@"童林杰3",@"老萧狗4"]
                                                   ]];
    
    DropDownView * dropDownView = [[DropDownView alloc] initWithFrame:CGRectMake(0, 64, 300, 40) delegate:self dataSource:self];
    dropDownView.backgroundColor = [UIColor lightGrayColor];
    dropDownView.mySuperView = self.view;
    self.view.backgroundColor = [UIColor magentaColor];
    [self.view addSubview:dropDownView];
}

- (void)dropDownView:(DropDownView *)dropDownView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"%li %li",indexPath.section,indexPath.row);
}

- (NSInteger)numberOfSectionsInDropDownView:(DropDownView *)dropDownView {
    return chooseArray.count;
}

- (NSInteger)dropDownView:(DropDownView *)dropDownView numberOfRowsInSection:(NSInteger)section {
    return [chooseArray[section] count];
}

- (NSString *)dropDownView:(DropDownView *)dropDownView titleForRowAtIndexPath:(NSIndexPath *)indexPath {
    return chooseArray[indexPath.section][indexPath.row];
}

- (NSInteger)defaultShowRow:(NSInteger)row {
    return 0;
}

主要思想:类比UITableView封装了一个DropDownView

继承于UIView遵守UITableViewDelegate和UITableViewDataSource封装的。

由section组和row行组成。

首先就是要把所有的数据显示在TableViewCell里面,如果currentExtendSection!=-1那么就是展开的,否则就是关闭的。

隐藏的时候最好把TableView以及BasciView清空,不然可能会导致内存泄露。

 

你可能感兴趣的:(iOS开发之下拉抽屉效果(DropDownView))