下拉列表框实现

下拉列表框实现

一、实现框架 1
二、实现根视图 1
三、实现DropDownList类 2
四、一些改进 6

cocoa touch不提供下拉框控件,因为他们提供了UIPickerView。为什么还要使用已经成为windows标准控件之一的下拉框呢?“这不是苹果的体验”——“苹果体验”推崇者们这样反对。但作为从windows开发平台转移过来的程序员,他们只需要一个理由就足够反驳了:UIPickerView太大了,远没有下拉框控件节省屏幕空间。真实情况就是这样的,放一个UIPickerView,足够放3个下拉框都绰绰有余了。
一、实现框架
1、新建一个Window-based-application。
2、新建一个UIViewController:RootViewController。在其loadView方法中增加:self.view=[[UIViewalloc]initWithFrame:
      [[UIScreenmainScreen]bounds]];

3、修改 AppDelegate,加入以下两句并导入相关类,使应用程序启动时加载一个RootViewController:
 RootViewController* root=[[RootViewControlleralloc]init];
 [windowaddSubview:root.view];

二、实现根视图
1、在根视图中添加几个文本框,用来模拟下拉列表框(后面实现),在loadView方法中加入代码:
 //1个textfield
 UITextField* tf=[[UITextFieldalloc]initWithFrame:
     CGRectMake(144,73,140,30)];
 tf.borderStyle=UITextBorderStyleRoundedRect;
 [self.viewaddSubview:tf];
 [tfrelease];

 //2个textfield
 tf=[[UITextFieldalloc]initWithFrame:
     CGRectMake(144,129,30)];
 tf.borderStyle=UITextBorderStyleRoundedRect;
 [self.viewaddSubview:tf];
 [tfrelease];
运行效果如下:


2、将上面的UITextField替换为DropDownList。下面,我们准备自己实现这个DropDownList。


三、实现DropDownList类
1、新建UIView子类DropDownList。
2、我们准备用一个文本输入框加上一个TableView控件来实现这个下拉框。在头文件中声明如下,注意相应的 @synthesize语句:
@interfaceDropDownList : UIView {
 UITextField* textField;//文本输入框
 NSArray* list;//下拉列表数据
 BOOLshowList;//是否弹出下拉列表
 UITableView* listView;//下拉列表
 CGRectoldFrame,newFrame;//整个控件(包括下拉前和下拉后)的矩形
 UIColor *lineColor,*listBgColor;//下拉框的边框色、背景色
 CGFloatlineWidth;//下拉框边框粗细
 UITextBorderStyleborderStyle;//文本框边框style
}
@property (nonatomic,retain)UITextField *textField;
@property (nonatomic,retain)NSArray* list;
@property (nonatomic,retain)UITableView* listView;
@property (nonatomic,retain)UIColor *lineColor,*listBgColor;
@property (nonatomic,assign)UITextBorderStyleborderStyle;
-(void)drawView;
@end
3、然后在initWithFrame方法中初始化变量, 并调用drawView绘制控件:
if(self=[superinitWithFrame:frame]){
  //默认的下拉列表中的数据
  list=[[NSArrayalloc]initWithObjects:@"1",@"2",@"3",@"4",nil];
  
  borderStyle=UITextBorderStyleRoundedRect;
  
  showList=NO; //默认不显示下拉框
  oldFrame=frame; //未下拉时控件初始大小
  //当下拉框显示时,计算出控件的大小。
  newFrame=CGRectMake(frame.origin.x,frame.origin.y,frame.size.width,frame.size.height*5);
  
  lineColor=[UIColorlightGrayColor];//默认列表边框线为灰色
  listBgColor=[UIColorwhiteColor];//默认列表框背景色为白色
  lineWidth=1;     //默认列表边框粗细为1
  
  //把背景色设置为透明色,否则会有一个黑色的边
  self.backgroundColor=[UIColorclearColor];
  [selfdrawView];//调用方法,绘制控件
  
 }
 returnself;
4、先在drawView方法中绘制一个文本框:
 //文本框
 textField=[[UITextFieldalloc]
   initWithFrame:CGRectMake(0,
          oldFrame.size.width,
          oldFrame.size.height)];
 textField.borderStyle=borderStyle;//设置文本框的边框风格
 [selfaddSubview:textField];
运行程序,进行测试。但我们点击DropDownList控件的输入框时,键盘会自动弹出,我们需要屏蔽掉它。在上面的代码后加上:
//增加文本框的触摸事件响应
 [textFieldaddTarget:selfaction:@selector(dropdown)
  forControlEvents:UIControlEventAllTouchEvents];
然后实现dropdown方法:
-(void)dropdown{
 [textFieldresignFirstResponder];
}
现在,键盘不会自动弹出了。
5、在drawView方法中添加代码,以绘制tableView控件:
 //下拉列表
 listView=[[UITableViewalloc]initWithFrame:
   CGRectMake(lineWidth,oldFrame.size.height+lineWidth,
      oldFrame.size.width-lineWidth*2,
      oldFrame.size.height*4-lineWidth*2)];
 listView.dataSource=self;
 listView.delegate=self;
 listView.backgroundColor=listBgColor;
 listView.separatorColor=lineColor;
 listView.hidden=!showList;//一开始listView是隐藏的,此后根据showList的值显示或隐藏

 [selfaddSubview:listView]; 
 [listViewrelease];
现在我们必须实现tableView的协议方法(别忘记在头文件中声明UITableViewDataSource和UITableViewDelegate协议):
#pragma mark listViewdataSource method and delegate method
-(NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section{
 returnlist.count;
}
-(UITableViewCell*)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath{
 staticNSString *cellid=@"listviewid";
 UITableViewCell* cell=[tableViewdequeueReusableCellWithIdentifier:cellid];
 if(cell==nil){
  cell=[[[UITableViewCellalloc]initWithStyle:UITableViewCellStyleDefault
         reuseIdentifier:cellid]autorelease];
 }
 //文本标签
 cell.textLabel.text=(NSString*)[listobjectAtIndex:indexPath.row];
 cell.textLabel.font=textField.font;
 
 cell.selectionStyle=UITableViewCellSelectionStyleGray;
 return cell;
}
-(CGFloat)tableView:(UITableView *)tableViewheightForRowAtIndexPath:(NSIndexPath *)indexPath{
 returnoldFrame.size.height;
}
//当选择下拉列表中的一行时,设置文本框中的值,隐藏下拉列表
-(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath{
 //NSLog(@"select");
 textField.text=(NSString*)[listobjectAtIndex:indexPath.row];
 //NSLog(@"textField.text=%@",textField.text);
 [selfsetShowList:NO];
}
setShowList是showList变量的setter方法。该方法根据给定的参数隐藏或显示下拉框。showList变量的访问方法如下:
-(BOOL)showList{//setShowList:No为隐藏,setShowList:Yes为显示
 returnshowList;
}
-(void)setShowList:(BOOL)b{
 showList=b;
 NSLog(@"showlist is set ");
 if(showList){
  self.frame=newFrame;
 }else {
  self.frame=oldFrame;
 }
 listView.hidden=!b;
}

运行程序,点击文本框,下拉框没有出来。别急,我们的dropdown方法还没有相关的代码:
 if (showList) {//如果下拉框已显示,什么都不做
  return;
 }else {//如果下拉框尚未显示,则进行显示
  //把dropdownList放到前面,防止下拉框被别的控件遮住
  [self.superviewbringSubviewToFront:self];
  [selfsetShowList:YES];//显示下拉框
 }
运行程序,点击文本框,下拉列表可以显示了。但是tableView是没有边框的:
 


要为下拉框加上边框,我们需要实现以下方法:
//为tableView加上边框
-(void)drawRect:(CGRect)rect{
 //NSLog(@"%@",rect);
 CGContextRefctx=UIGraphicsGetCurrentContext();
 CGRectdrawRect;
 if (showList) {
  CGContextSetStrokeColorWithColor(ctx,[lineColorCGColor]);
  drawRect=listView.frame;
  CGContextStrokeRect(ctx,drawRect);
  //CGContextStrokeRectWithWidth(ctx,drawRect,lineWidth);
 }else {
  return;
 }
 //[selfdrawListBorder:ctx :drawRect];
}
这个方法会在收到setNeedsDisplay方法时被调用,因此我们需要在显示下拉列表时,发送setNeedsDisplay消息。在setShowList方法最后发送setNeedsDisplay消息:
[selfsetNeedsDisplay];//调用drawRect重绘
运行效果如下:
 


如果我们要在列表中显示自己的数据,可以在构造dropDownList后对list属性赋值:
 DropDownList* tf=[[DropDownListalloc]initWithFrame:
     CGRectMake(144,30)];
 tf.borderStyle=UITextBorderStyleRoundedRect;
 tf.textField.placeholder=@"请输入联系方式";
 NSArray* arr=[[NSArrayalloc]initWithObjects:@"电话",@"email",@"手机",nil];
 tf.list=arr;
 [arrrelease];
 [self.viewaddSubview:tf];
 [tfrelease];

运行效果如下:
 


四、一些改进
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=[[NSDictionarydictionaryWithObjectsAndKeys:
   @"市场部",@"1",@"行政部",nil]retain];
allKeys=[list.allKeysretain];
⋯⋯
-(void)setList:(NSDictionary *)val{
 list=val;
 allKeys=val.allKeys;
 allKeys.retain;
 [listViewreloadData]; //刷新textView显示
 textField.text=@"";//清空文本框内容,不能让文本框的内容与下拉列表中的内容不一致
}
同时修改tableView数据源方法和委托方法中的代码:
-(UITableViewCell*)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath{
⋯⋯
//获得字典中的键和值
 NSString* sKey=[list.allKeysobjectAtIndex:indexPath.row];
 NSString* sVal=(NSString*)[listobjectForKey:skey];
 //文本标签
 cell.textLabel.tag=sKey;
 cell.textLabel.text=sVal;
 [sKeyrelease];
 [sValrelease];
⋯⋯

-(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath{
 //获得字典中的键和值
 data=[allKeysobjectAtIndex:indexPath.row];
 textField.text=(NSString*)[listobjectForKey:data];
 [selfsetShowList:NO];
}
现在仅仅是构造一个DropDownList对象,不用修改什么属性,结果如下:
 


当你选择一个下拉选项后,文本框内的文字会发生改变。
2、定义协议并通过委托进行扩展
仅仅是显示列表供用户选择,而不进行任何动作显然是不够的。我们可以定义一个委托属性,把选择后的动作交给委托来做。
首先,需要在头文件中定义要委托的工作,即协议:
@protocolDropDownListDelegate

@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) {
  [delegateperformSelector:@selector(selected:displayLabel:)
     withObject:datawithObject:textField.text];
 }
回到RootViewController,在interface部分,再类名后增加<DropDownListDelegate>
在loadView方法中增加droplist.delegate=self;
最后实现协议中定义的方法:
-(void)selected:(NSString *)k displayLabel:(NSString *)v{
 NSLog(@"%@:%@",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:行政部通过委托和协议的方式对类进行扩展,与通过子类进行扩展比较而言,显然更加的灵活,代码更为分散。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


我正在用TitaniumDeveloper编写一个应用程序,它允许我使用Javascript,PHP,Ruby和Python.它为API提供了一些可能需要的标准功能,但缺少的是全局事件.现在我想将全局热键分配给我的应用程序并且几乎没有任何问题.现在我只针对MAC,但无法找到任何Python或Ruby的解决方案.我找到了Coc
我的问题是当我尝试从UIWebView中调用我的AngularJS应用程序中存在的javascript函数时,该函数无法识别.当我在典型的html结构中调用该函数时,该函数被识别为预期的.示例如下:Objective-C的:-(void)viewDidLoad{[superviewDidLoad];//CODEGOESHERE_webView.d
我想获取在我的Mac上运行的所有前台应用程序的应用程序图标.我已经使用ProcessManagerAPI迭代所有应用程序.我已经确定在processMode中设置了没有modeBackgroundOnly标志的任何进程(从GetProcessInformation()中检索)是一个“前台”应用程序,并显示在任务切换器窗口中.我只需要
我是一名PHP开发人员,我使用MVC模式和面向对象的代码.我真的想为iPhone编写应用程序,但要做到这一点我需要了解Cocoa,但要做到这一点我需要了解Objective-C2.0,但要做到这一点我需要知道C,为此我需要了解编译语言(与解释相关).我应该从哪里开始?我真的需要从简单的旧“C”开始,正
OSX中的SetTimer在Windows中是否有任何等效功能?我正在使用C.所以我正在为一些软件编写一个插件,我需要定期调用一个函数.在Windows上,我只是将函数的地址传递给SetTimer(),它将以给定的间隔调用.在OSX上有一个简单的方法吗?它应该尽可能简约.我并没有在网上找到任何不花哨的东西
我不确定引擎盖下到底发生了什么,但这是我的设置,示例代码和问题:建立:>雪豹(10.6.8)>Python2.7.2(由EPD7.1-2提供)>iPython0.11(由EPD7.1-2提供)>matplotlib(由EPD7.1-2提供)示例代码:importnumpyasnpimportpylabasplx=np.random.normal(size=(1000,))pl.plot
我正在使用FoundationFramework在Objective-C(在xCode中)编写命令行工具.我必须使用Objective-C,因为我需要取消归档以前由NSKeyedArchiver归档的对象.我的问题是,我想知道我现在是否可以在我的Linux网络服务器上使用这个编译过的应用程序.我不确定是否会出现运行时问题,或者可
使用cocoapods,我们首先了解一下rvm、gem、ruby。rvm和brew一样,但是rvm是专门管理ruby的版本控制的。rvmlistknown罗列出ruby版本rvminstall版本号   可以指定更新ruby版本而gem是包管理gemsource-l查看ruby源gemsource-rhttps://xxxxxxxx移除ruby源gemsou
我有一个包含WebView的Cocoa应用程序.由于应用程序已安装客户群,我的目标是10.4SDK.(即我不能要求Leopard.)我有两个文件:index.html和data.js.在运行时,为了响应用户输入,我通常会使用应用程序中的当前数据填充data.js文件.(data.js文件由body.html上的index.html文件用于填充
如何禁用NSMenuItem?我点击后尝试禁用NSMenuItem.操作(注销)正确处理单击.我尝试通过以下两种方式将Enabled属性更改为false:partialvoidLogout(AppKit.NSMenuItemsender){sender.Enabled=false;}和partialvoidLogout(AppKit.NSMenuItemsender){LogoutI
我在想,创建一个基本上只是一个带Web视图的界面的Cocoa应用程序是否可行?做这样的事情会有一些严重的限制吗?如果它“可行”,那是否也意味着你可以为Windows应用程序做同样的事情?解决方法:当然可以创建一个只是一个Cocoa窗口的应用程序,里面有一个Web视图.这是否可以被称为“可可应
原文链接:http://www.cnblogs.com/simonshi2012/archive/2012/10/08/2715464.htmlFrom:http://www.idev101.com/code/Cocoa/Notifications.htmlNotificationsareanincrediblyusefulwaytosendmessages(anddata)betweenobjectsthatotherwi
如果不手动编写GNUmake文件,是否存在可以理解Xcode项目的任何工具,并且可以直接针对GNUstep构建它们,从而生成Linux可执行文件,从而简化(略微)保持项目在Cocoa/Mac和GNUstep/Linux下运行所需的工作?基本上,是否有适用于Linux的xcodebuild样式应用程序?几个星期前我看了pbtomake
我正在将页面加载到WebView中.该页面有这个小测试Javascript:<scripttype="text/javascript">functiontest(parametr){$('#testspan').html(parametr);}varbdu=(function(){return{secondtest:function(parametr){$('#testspan&#039
我正在尝试使用NSAppleScript从Objective-C执行一些AppleScript…但是,我正在尝试的代码是Yosemite中用于自动化的新JavaScript.它在运行时似乎没有做任何事情,但是,正常的AppleScript工作正常.[NSAppactivateIgnoringOtherApps:YES];NSAppleScript*scriptObject=[[NSApple
链接:https://pan.baidu.com/s/14_im7AmZ2Kz3qzrqIjLlAg           vjut相关文章Python与Tkinter编程ProgrammingPython(python编程)python基础教程(第二版)深入浅出PythonPython源码剖析Python核心编程(第3版)图书信息作者:Kochan,StephenG.出
我正在实现SWTJava应用程序的OSX版本的视图,并希望在我的SWT树中使用NSOutlineView提供的“源列表”选项.我通过将此代码添加到#createHandle()方法来破解我自己的Tree.class版本来实现这一点:longNSTableViewSelectionHighlightStyleSourceList=1;longhi=OS.sel_regist
我的Cocoa应用程序需要使用easy_install在用户系统上安装Python命令行工具.理想情况下,我想将一个bash文件与我的应用程序捆绑在一起然后运行.但据我所知这是不可能的,因为软件包安装在Python的“site-packages”目录中.有没有办法创建这些文件的“包”?如果没有,我应该如何运行ea
摘要: 文章工具 收藏 投票评分 发表评论 复制链接 Swing 是设计桌面应用程序的一个功能非常强大工具包,但Swing因为曾经的不足常常遭到后人的诟病.常常听到旁人议论纷纷,”Swing 运行太慢了!”,”Swing 界面太丑嘞”,甚至就是说”Swing 简直食之无味”. 从Swing被提出到现在,已是十年光景,Swing早已不是昔日一无是处的Swing了. Chris Adamson 和我写
苹果的开发:   我对于Linux/Unix的开发也是一窍不通,只知道可以用Java.不过接触了苹果过后,确实发现,世界上确实还有那么一帮人,只用苹果,不用PC的.对于苹果的开发,我也一点都不清楚,以下是师兄们整理出来的网站. http://www.chezmark.com/osx/    共享软件精选 http://www.macosxapps.com/    分类明了,更新及时的一个重要Mac