一、实现框架
二、实现根视图
三、实现DropDownList类
四、一些改进
cocoa touch不提供下拉框控件,因为他们提供了UIPickerView。为什么还要使用已经成为windows标准控件之一的下拉框呢?“这不是苹果的体验”——“苹果体验”推崇者们这样反对。但作为从windows开发平台转移过来的程序员,他们只需要一个理由就足够反驳了:UIPickerView太大了,远没有下拉框控件节省屏幕空间。真实情况就是这样的,放一个UIPickerView,足够放3个下拉框都绰绰有余了。
一、实现框架
1、新建一个Window-based-application。
2、新建一个UIViewController:RootViewController。在其loadView方法中增加:self.view=[[UIViewalloc]initWithFrame:
3、修改 AppDelegate, 加入以下两句并导入相关类,使应用程序启动时加载一个RootViewController:
二、实现根视图
1、在根视图中添加几个文本框,用来模拟下拉列表框(后面实现),在loadView方法中加入代码:
运行效果如下:
2、将上面的UITextField替换为DropDownList。下面,我们准备自己实现这个DropDownList。
三、实现DropDownList类
1、新建UIView子类DropDownList。
2、我们准备用一个文本输入框加上一个TableView控件来实现这个下拉框。在头文件中声明如下,注意相应的 @synthesize语句:
@interfaceDropDownList : UIView {
}
@property (nonatomic,retain)UITextField *textField;
@property (nonatomic,retain)NSArray* list;
@property (nonatomic,retain)UITableView* listView;
@property (nonatomic,retain)UIColor *lineColor,*listBgColor;
@property (nonatomic,assign)UITextBorderStyleborderS
-(void)drawView;
@end
3、然后在initWithFrame方法中初始化变量, 并调用drawView绘制控件:
if(self=[superinitWithFrame:frame]){
4、先在drawView方法中绘制一个文本框:
运行程序,进行测试。但我们点击DropDownList控件的输入框时,键盘会自动弹出,我们需要屏蔽掉它。在上面的代码后加上:
//增加文本框的触摸事件响应
然后实现dropdown方法:
-(void)dropdown{
}
现在,键盘不会自动弹出了。
5、在drawView方法中添加代码,以绘制tableView控件:
现在我们必须实现tableView的协议方法(别忘记在头文件中声明UITableViewDataSource和UITableViewDelegate协议):
#pragma mark listViewdataSource method and delegate method
-(NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section{
}
-(UITableViewCell*)tableView:(UITableView *)tableViewcellForRowAtInd
}
-(CGFloat)tableView:(UITableView *)tableViewheightForRowAtI
}
//当选择下拉列表中的一行时,设置文本框中的值,隐藏下拉列表
-(void)tableView:(UITableView *)tableViewdidSelectRowAtI
}
setShowList是showList变量的setter方法。该方法根据给定的参数隐藏或显示下拉框。showList变量的访问方法如下:
-(BOOL)showList{//setShowList:No为隐藏,setShowList:Yes为显示
}
-(void)setShowList:(BOOL)b{
}
运行程序,点击文本框,下拉框没有出来。别急,我们的dropdown方法还没有相关的代码:
运行程序,点击文本框,下拉列表可以显示了。但是tableView是没有边框的:
要为下拉框加上边框,我们需要实现以下方法:
//为tableView加上边框
-(void)drawRect:(CGRect)rect{
}
这个方法会在收到setNeedsDisplay方法时被调用,因此我们需要在显示下拉列表时,发送setNeedsDisplay消息。在setShowList方法最后发送setNeedsDisplay消息:
[selfsetNeedsDisplay];//调用drawRect重绘
运行效果如下:
如果我们要在列表中显示自己的数据,可以在构造dropDownList后对list属性赋值:
运行效果如下:
四、一些改进
1、使用NSDictionary作为模型数据
由于下拉框选项一般会由两部分的数据构成:显示文本和数据,所以使用由“键-值”对组成的Dictionary类型来表示下拉框的数据模型更为适宜。因此我们把DropDownList的list修改为NSDictionary类型:
NSString* data;//变量,存储选中项的key值
NSDictionary* list;//下拉列表数据
NSArray* allKeys;//所有键
⋯⋯
@property (nonatomic,retain)NSString* data;
-(void)setList:(NSDictionary *)val;
⋯⋯
@synthesize data
⋯⋯
list=[[NSDictionarydictionaryWi
allKeys=[list.allKeysretain];
⋯⋯
-(void)setList:(NSDictionary *)val{
}
同时修改tableView数据源方法和委托方法中的代码:
-(UITableViewCell*)tableView:(UITableView *)tableViewcellForRowAtInd
⋯⋯
//获得字典中的键和值
⋯⋯
}
-(void)tableView:(UITableView *)tableViewdidSelectRowAtI
}
现在仅仅是构造一个DropDownList对象,不用修改什么属性,结果如下:
当你选择一个下拉选项后,文本框内的文字会发生改变。
2、定义协议并通过委托进行扩展
仅仅是显示列表供用户选择,而不进行任何动作显然是不够的。我们可以定义一个委托属性,把选择后的动作交给委托来做。
首先,需要在头文件中定义要委托的工作,即协议:
@protocolDropDownListDele
@required
-(void)selected:(NSString*)k displayLabel:(NSString*)v;
@end
其次,在头文件中定义一个id属性:
id<DropDownListDelegate>delegate;//委托,当选定下拉项后处理
⋯⋯
@property (nonatomic,assign)id<DropDownListDelegate> delegate;
然后在implementation部分@synthesize delegate;
并在-(void)tableView: didSelectRowAtIndexPath:方法中加入:
if (delegate!=nil) {
回到RootViewController,在interface部分,再类名后增加<DropDownListDelegate>
在loadView方法中增加droplist.delegate=self;
最后实现协议中定义的方法:
-(void)selected:(NSString *)k displayLabel:(NSString *)v{
}
运行程序,选择下拉项,委托方法(协议方法)会被调用,后台输出如下:
2010-08-17 15:13:05.104 DropDownBox[3048:207] 1:市场部
2010-08-17 15:13:07.288 DropDownBox[3048:207] 2:行政部
2010-08-17 15:13:09.153 DropDownBox[3048:207] 1:市场部
2010-08-17 15:13:11.371 DropDownBox[3048:207] 2:行政部
通过委托和协议的方式对类进行扩展,与通过子类进行扩展比较而言,显然更加的灵活,代码更为分散。