iOS自定义控件之下拉列表按钮

来源:互联网 发布:windows操作系统原理 编辑:程序博客网 时间:2024/04/29 03:54

本文将介绍如何实现一个简单的下拉列表按钮,使读者能够更进一步掌握UIButton类和UITableView类的使用,了解非iOS系统自带控件的初始化方法,学习列表下拉、收起的动画效果,编写可重用的DropDownButton类,还可以对此进行优化、扩展和整理,便于以后项目实战中直接拿来进行使用。


----------------------------------------------------------------------------------------------------------我是分割线--------------------------------------------------------------------------------------------------------------
完成效果图

----------------------------------------------------------------------------------------------------------这里是正文--------------------------------------------------------------------------------------------------------------

1. 创建类DropDownButton

  • 在Xcode中创建一个新的Cocoa Touch Class,取名DropDownButton,继承UIButton,使用ARC
  • 打开DropDownButton.h文件,声明类成员及相应方法,编写代码如下:

@property (nonatomic, copy) NSString *title;@property (nonatomic, copy) NSArray *list;/** *  初始化DropDownButton * *  @param frame 结构 *  @param title 标题 *  @param list  下拉列表 * *  @return DropDownButton实例 */- (instancetype)initWithFrame:(CGRect)frame Title:(NSString*)title List:(NSArray *)list;

  • 打开DropDownButton.m文件,在顶部添加以下代码:
static NSString *CellIdentifier = @"DropDownCell";@interface GYCDropDownButton () <UITableViewDataSource, UITableViewDelegate> {    UITableView *listView;}@end

至此,DropDownButton类成员、类方法和相应变量声明完成,下面开始实现。

2. 实现下拉列表

继续在DropDownButton.m文件中编写代码:
  • 设置表视图listView的布局、数据源和代理
- (void)setupDefaultTable {    //将listView放在当前按钮下方位置,保持宽度相同,初始高度设置为0    listView = [[UITableView alloc] initWithFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y+self.frame.size.height, self.frame.size.width, 0) style:UITableViewStylePlain];        listView.dataSource = self;    listView.delegate = self;}
  • 添加listView的下拉动画、收起动画方法
- (void)startDropDownAnimation {    CGRect frame = listView.frame;    //使listView高度在0.3秒内从0过渡到最大高度以显示全部列表项    frame.size.height = self.frame.size.height*self.list.count;    [UIView animateWithDuration:0.3 animations:^{        listView.frame = frame;    } completion:^(BOOL finished) {            }];}- (void)startPackUpAnimation {    CGRect frame = listView.frame;    //使listView高度在0.3秒内从最大高度过渡到0以隐藏全部列表项    frame.size.height = 0;    [UIView animateWithDuration:0.3 animations:^{        listView.frame = frame;    } completion:^(BOOL finished) {            }];}
  • 添加按钮点击事件,每点击一次按钮,tag值自加1,然后根据tag值执行下拉或收起列表动画,最后重新加载一次listView的数据,防止串改列表项后不能及时更新到listView中
- (void)clickedToDropDown {    self.tag++;    self.tag%2 ? [self startDropDownAnimation] : [self startPackUpAnimation];        [listView reloadData];}


  • 实现listView的数据源和代理
#pragma mark - table view data source- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {    return 1;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {    //根据成员list数组中的元素数返回列表的行数,必须保证self.list不为nil,才会调用cellForRowAtIndexPath方法    return self.list.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];    if (nil == cell) {        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];    }    //设置列表中的每一项文本、字体、颜色等    cell.textLabel.text = self.list[indexPath.row];    cell.textLabel.font = self.titleLabel.font;    cell.textLabel.textColor = self.titleLabel.textColor;        return cell;}#pragma mark - table view delegate- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {    //选择某项后,使按钮标题内容变为当前选项    [self setTitle:self.list[indexPath.row] forState:UIControlStateNormal];    //执行列表收起动画    [self clickedToDropDown];}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {    //设置表单元高度为按钮高度    return self.frame.size.height;}


  • 设置DropDownButton的初始化
- (void)setup {    [self setTitle:self.title forState:UIControlStateNormal];    [self setupDefaultTable];    [self setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];    [self addTarget:self action:@selector(clickedToDropDown) forControlEvents:UIControlEventTouchUpInside];}


通过initWithFrame方法实例化DropDownButton对象,先必须实现事先声明的初始化方法,由于initWithFrame时,DropDownButton对象的父视图肯定为nil,所以还需要重写didMoveToSuperview,当下拉列表按钮被添加进某一视图上后将listView一同添加到该视图上去。
- (instancetype)initWithFrame:(CGRect)frame Title:(NSString*)title List:(NSArray *)list {    self = [super initWithFrame:frame];    if (self) {        self.title = [NSString stringWithString:title];        self.list = [NSArray arrayWithArray:list];                [self setup];    }        return self;}- (void)didMoveToSuperview {    [self.superview addSubview:listView];}


通过Interface Builder直接在xib中添加DropDownButton对象,需要重写awakeFromNib方法,将listView添加到同一父视图上去,这里由于xib文件缘故,self.surperview不为nil。
- (void)awakeFromNib {    self.title = self.titleLabel.text;    [self setup];    [self.superview addSubview:listView];}


3. 调试运行

在你的view controller中导入DropDownButton.h文件
  • 使用代码
    DropDownButton *button = [[DropDownButton alloc] initWithFrame:CGRectMake(40, 268, 240, 30) Title:@"请选择性别" List:@[@"男", @"女"]];    [self.view addSubview:button];


  • 使用Interface Builder
拖拽Xcode对象库中的Button控件进入xib的相应view中,在Attributes面板进行相关设置后修改Identity面板中的Class值UIButton为DropDownButton



再添加到一个输出口
@property (retain, nonatomic) IBOutlet DropDownButton *button;

最后在viewDidLoad方法中编写代码,设置好其属性list
    button.list = @[@"男", @"女"];


运行即可

----------------------------------------------------------------------------------------------------------我是分割线--------------------------------------------------------------------------------------------------------------
注:要得到列表选择某项的内容,需要调用UIButton对象方法titleForState:UIControlStateNormal得到,而不是通过DropDownButton对象的属性成员title得到,这里的title是按钮最初始的标题内容,读者可以对此进行修改,也可以根据自己喜好来扩展此类,如添加一些表单元的样式风格、更华丽的动画效果、更快捷的数据获取等。

源码下载地址:https://github.com/ganyuchuan/GYCBox,详见GYCDropDownButton。

0 0
原创粉丝点击