UIdatePicker&UIPickerView简单使用
/***********************************************************************************/
一:UIdatePicker:(日期控件)
1.UIDatePicker什么时候用? 当用户选择日期的时候,一般弹出一个UIDatePicker给用户选择。
2.UIDatePickerios6和ios7/8的区别
下面看看使用封装的代码怎么去实现它:
因为这个比较简单,所以这里只是简单给出了封装之后UIDatePicker的实现代码
由于我们平时一般都是使用它用来输入一些日期到我们想要的地方,特别是文本框,所以如果我们要封装也是在文本框里面封装,因为文本框邮一个属性inputView,我只要在里面将我们的UIDatePicker设置为这个属性就可以。
-(void)awakeFromNib { [self initWithBirthView]; } -(instancetype)initWithFrame:(CGRect)frame { if (self == [super initWithFrame:frame]) { [self initWithBirthView]; } return self; } -(void)initWithBirthView { UIDatePicker *date = [[UIDatePicker alloc] initWithFrame:CGRectMake(, , , )]; date.locale = [NSLocale localeWithLocaleIdentifier:@"zh"]; date.datePickerMode = UIDatePickerModeDate; [date addTarget:self action:@selector(changeData:) forControlEvents:UIControlEventValueChanged]; self.inputView = date; } -(void)changeData:(UIDatePicker *)datePicker { NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; fmt.dateFormat = @"yyyy-MM-dd"; NSString *data = [fmt stringFromDate:datePicker.date]; self.text = data; }
当我们滚动下面的转盘是文本框也会动态的现实对应的时间:
/********************************************************************************************/
二:UIPickerView:(轮转控件)
这里先说一下UIPickerView相对UIDatePicker要难一点,他的使用类似tableView,但是如果你只是要简单的实现那就没你想的那么难的,不过这个在实际开发中一般很少用到,就算真的用到了我们一一般也是使用已经封装好的直接拿来用。
1.UIPickView什么时候用?
• 通常在注册模块,当用户需要选择一些东西的时候,比如说城市,往往
弹出一个PickerView给他们选择。
2.UIPickView常见用法,演示实例程序 1>独立的,没有任何关系 =>菜单系统。 2>相关联的,下一列和第一列有联系=>省会城市选择 3>图文并帽,=>国旗选择。
3.UIPickView
搭建界面
1> 注意点:PickerView的高度不能改,默认162,PickerView里面每行的高度 可以改,不要弄混淆了。
2.pickerView显示数据
- 1> 如何使用PickerView展示数据? 进入PickerView头文件,有数据源和代理,联想到UITableView,模仿 UITableView的用法。
- 2> 让控制器作为PickerView的数据源,控制器遵守PickerView的数据源方法
2.1>两种方式:1.拖线 2.代码 2.2>系统自带的控件,数据源和代理属性不需要IBOutlet,也能拖 线。自己的属性,想要拖线,必须写IBOutlet。
3> PickerView的数据源方法
- 1> numberOfComponentsInPickerView: 返回多少列
- 2> pickerView:numberOfRowsInComponent: 返回第component列有多少 行
- 3> 和UITableView的区别,每一行长什么样,是由PickerView的代理决 定的。
- 4> 注意:如果没有返回每一行长什么样子,每行就会显示?,看见?,就 知道没有实现每一行长什么样子的方法。
4> PickerView的代理方法
1> 返回第component列第row行长什么样。
- 第component列第row行的展示标题
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
- 第component列第row行带属性的标题
- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger) component
- 第component列第row行展示的视图
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
2> 返回第component列每一行的高度和宽度
- - (CGFloat)pickerView:(UIPickerView *)pickerView
- - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
2> 返回第component列每一行的高度和宽度
- - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;
- - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component;
3> 选中第component列第row行调用
- - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;
3. 加载plist数据
- 1> 分析数据结构
- 1> 大数组元素个数:多少列 2>大数组里面的小数组: 这一列有多少行。 3> 小数组里的字符串: 每行展示的样子
4.处理菜单选中业务
- 1> 选中某一列某一行,显示出来
- 2> 拖动不同列,改变不同的label,拖动第一列改变水果。
- 3> 判断拖动哪一列,改变对应的label
- 4> 在viewDidLoad中初始化label显示
- 5> 取出数组中的数据给label直接赋值 _fruitLabel.text = self.foots[0][0]; 这种 方式不好,如果以后数组里有很多数据,要写很多行。
- 6> 还有另外一种方式,通过调用代理,给label赋值.唯一不同的,就是列 数,搞个for循序就好了。
5.随机选中某一列的某一行
1> 如何选中某一行 [self.pickerView selectRow:row inComponent:component
animated:YES];
2> 先随机选中第0列的某一行,随机数取值范围看第0列总共有多少行,
arc4random_uniform(x)随机0~x-1的数
3> 避免随机出来的行数都一样,需要判断下,随机出来的行数和当前选中 的是否一样,一样就重新随机,用while判断,直到随机到不一样,才行。 3> 问题:label没有显示最新选中的一行。
原因:手动调用pickview滚动,选中某一行,不会触发代理,我们自己 主动调用代理,让lebel显示选中哪一行.
注意:只有用户手动滚动才可以触发pickview的代理方法。 4> 每一列都要随机选中,弄个for循序,遍历每一列都随机选中
下面就以代码的方式封装实现一下他:
关于UIPickView,我们知道他使用最多的地方就是在关于区域的选择,比如我们平时在使用一个App或者想要做某些是的时候,上面都需要我们滚动他来告诉他们对应的地址。
所以今天我吗就一地址的实现来封装一个UIPickView,关于其他一些只要会了这个基本上就没有任何问题了,因为这里涉及到了多列动态的现实数据。
首先我们来看看我们需要的plist数据,这里只有部分天朝区域
既然是程序员我们必定要想到MVC,所以根据plist文件创建模型,创建对应的属性,并且模型方法,将字典转成模型:
#import <Foundation/Foundation.h> @interface AddressModel : NSObject @property (nonatomic, copy) NSString *name; @property (nonatomic, copy) NSArray *cities; +(instancetype)addWithDict:(NSDictionary *)dict; @end
由于plsit比较简单,所以这里直接使用KVC,关于plist和字典转模型,请查看:。。。。。。,这里非常详细的介绍
#import "AddressModel.h" @implementation AddressModel +(instancetype)addWithDict:(NSDictionary *)dict { AddressModel *model = [[self alloc] init]; [model setValuesForKeysWithDictionary:dict]; return model; } @end
然后同上,由于我们需要实现的事讲选中的内容输入到对应的文本框上面显示,所以先自定义一个继承自UItextFiled得类:
#import <UIKit/UIKit.h> @interface AddressView : UITextField @end
然后在里面创建我们需要的:注意这里最关键的是最后一行代码,没有这里一切都是扯蛋
-(void)initWithAddressView { UIPickerView *pick = [[UIPickerView alloc] initWithFrame:CGRectMake(, , , )]; self.pick = pick; pick.delegate = self; pick.dataSource = self; self.inputView = pick; }
因为我们是要直接使用这个类,但是由于项目的需要,我们可能是使用StoryBoard创建也可能是使用纯代码创建所以,我们需要在两个方法中调用这个初始化的方法:
//纯代码创建
-(instancetype)initWithFrame:(CGRect)frame { if (self == [super initWithFrame:frame]) { [self initWithAddressView]; } return self; } //从文件(Xib/StoryBoard创建) -(void)awakeFromNib { [self initWithAddressView]; }
关于懒加载就不多说了,说太多我也累,直接上代码:
@property (nonatomic, strong) NSArray *cityArr; -(NSArray *)cityArr { if (_cityArr == nil) { NSArray *arr = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cities.plist" ofType:nil]]; NSMutableArray *cityArr = [NSMutableArray array]; for (NSDictionary *dict in arr) { AddressModel *model = [AddressModel addWithDict:dict]; [cityArr addObject:model]; } _cityArr = cityArr; } return _cityArr; }
后面就是关键了,同时也是使用这个控件的一个难点:
遵守协议:
<UIPickerViewDataSource, UIPickerViewDelegate>
由于我们每选中第一列之后都要根据第一列中根据对应的选中项去处里面对应的子项(也就是城市),所以这里需要定义一个变量来记录一下我们选中的第一列:
@property (nonatomic, assign) NSInteger selectCom;
实现必须实现的代理方法:
/******************************************************************************
* *
* UIPickerView代理方法 *
* *
* iCocos--Description *
* *
******************************************************************************/
//列数
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { ; }
//对应列的行数
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { //如果是第0列 ) { //直接返回懒加载数组元素的个数 return self.cityArr.count; } else { //否则就是第一列了(因为这里只有两列) //根据选中的第一列从数组中取出来,放到一个模型里面 AddressModel *model = self.cityArr[_selectCom]; //再根据这个模型里面的子项cities里面的元素个数返回对应的行数 return model.cities.count; } }
每列显示的标题文字
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { //如果是第0列 ) { //直接返回懒加载数组元素中对应为name的值 return [self.cityArr[row] name]; } else { //根据选中的第一列从数组中取出来,放到一个模型里面 AddressModel *model = self.cityArr[_selectCom]; //再根据这个模型里面的子项cities,取出里面的每一行返回来显示在第二列中 return model.cities[row]; } }
根据选中显示对应的数据;
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { //如果是第0列 ) { //记录选中第0列的项 self.selectCom = [pickerView selectedRowInComponent:]; //刷新数据(类似tableView的reLoadData) [pickerView reloadComponent:]; //默认选中项 [pickerView selectRow: inComponent: animated:YES]; } else { //根据选中的第一列从数组中取出来,放到一个模型里面 AddressModel *model = self.cityArr[_selectCom]; //将选中的第一列使用一个变量再次纪录一下 NSInteger sel = [pickerView selectedRowInComponent:]; //根据选中的第一列从cities里面取出对应子元素的所有元素,保存到一个字符串 NSString *name = model.cities[sel]; //根据UIPickerView上面对应列,对应行的数据动态的刷新并且显示到文本框中 self.text = [NSString stringWithFormat:@"%@ %@", model.name, name]; } }
如下图:
当我们滚动最后选中左边一行之后右边会根据左边的现实做相应的改变,当我们在滚动最后选中右边列的任意项的时候,文本框根据两个现实的项取得对应的文字显示在界面上:
那么以后如果我需要使用这个或者是类似的,只需要把我们封装好的导入到项目中,然后将我们对应的textField的类设置为我们这里的类酒可以实现了,只需哟做少量的修改!