UIPickView 和 UIDatePicker
UIPickView 和 UIDatePicker
1.UIPickView什么时候用?
- 通常在注册模块,当用户需要选择一些东西的时候,比如说城市,往往 弹出一个PickerView给他们选择。
- 2.UIPickView常见用法
- 独立的,没有任何关系 =>菜单系统。
- 相关联的,下一列和第一列有联系=>省会城市选择
- 图文并茂,=>国旗选择。
- 3.UIDatePicker什么时候用?
- 当用户选择日期的时候,一般弹出一个UIDatePicker给用户选择。
01-UIPickView的基本使用
- UIPickView和TableView一样,想要展示数据也要设置数据源和代理
- 设置数据源
- self.pickView.dataSource = self;
- 设置代理
- self.pickView.delegate = self;
遵守数据源,代理协议:
@interface ViewController () <UIPickerViewDataSource,UIPickerViewDelegate> @property (weak, nonatomic) IBOutlet UIPickerView *pickView; @end
实现数据源代理方法:
总共有多少列 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{ return 3; }第component列有多少行. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{ return 4; }返回每一列的宽度 - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent: (NSInteger)component{ }返回第几列的高度 - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{ return 50; }返回每一列的标题 - (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{ return @"gaowei"; }返回每一列的视图UIView - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow: (NSInteger)row forComponent:(NSInteger)component reusingView: (nullable UIView *)view{UIButton *btn = [UIButton buttonWithType:UIButtonTypeContactAdd]; return btn; }
02-UIPickView简单Demo
- import "ViewController.h"
@interface ViewController ()<UIPickerViewDataSource,UIPickerViewDelegate> //展示数据的pickView @property (weak, nonatomic) IBOutlet UIPickerView *pickView;//数组当中有3个数组,每个数组代表一列.每一列数组的个数代表这列有多少行. @property(nonatomic,strong) NSArray *foodArray;//显示当前选中的食物 @property (weak, nonatomic) IBOutlet UILabel *foodLabel; @end @implementation ViewController //懒加载数据 -(NSArray *)foodArray{ if (_foodArray == nil) { //获取Plist文件的路径 NSString *filePath = [[NSBundle mainBundle] pathForResource:@"foods.plist" ofType:nil]; //从Plist文件当中加载数组. _foodArray = [NSArray arrayWithContentsOfFile:filePath]; } return _foodArray; }- (void)viewDidLoad { [super viewDidLoad]; //设置数据源和代理 self.pickView.dataSource = self;
self.pickView.delegate = self; }//总共有多少列 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{ //数组当中有几个元素, 就展示多少列.每个元素代表一列, return self.foodArray.count; } //第component列有多少行. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent: (NSInteger)component{ //取出当前所在的列.每一列都是一个数组. NSArray *array = self.foodArray[component]; 返回每一组当中, 每个数组的个数, 也就是这组有多少行.return array.count; }返回每一行的标题 - (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow: (NSInteger)row forComponent:(NSInteger)component{ //取出当前所在的列.每一列都是一个数组. NSArray *componentArray = self.foodArray[component]; //返回数组当中每一个元素 return componentArray[row]; }//点击了哪列的哪一行 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{ NSString *food = self.foodArray[component][row]; self.foodLabel.text = food; }
03-拦截用户输入
- 通过设置代理的方式来去监听文件框的改变//是否允许开始编辑- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{ return YES;}//开始编辑时调 ,(弹出键盘)became first responder- (void)textFieldDidBeginEditing:(UITextField *)textField{NSLog(@"弹出键盘"); }//是否允许结束编辑.- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{return YES;
}//结束编辑时调用.- (void)textFieldDidEndEditing:(UITextField *)textField{NSLog(@"结束编辑时调用.");
}//是否允许文字改变.//拦截用户输入.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{return NO;
}
04- 定义国旗键盘
运行例效果:
- 点击国家时弹出的是一个国旗键盘.
实现这种效果采取的方案是自定义一个TextField.修改它的弹出键盘为 个UIPickView.
对应的模型:
#import <UIKit/UIKit.h> 注意:这里继承的是UITextField @interface FlagField : UITextField @end//这个是自定义的pickView每一行的一个UIView. #import "FlagView.h" #import "FlagItem.h"//
这个是每一行对应的模型. @interface FlagField()<UIPickerViewDataSource,UIPickerViewDelegate> //保存加载的过期数组. @property(nonatomic,strong) NSMutableArray *flagArray; @end@implementation FlagField //加载数据 //数据内容对应的模型图://数组当中保存的都是字典.我们看到字典就会它转成模型. 所以新建了一个 FlagItem模型,FlagItem每一个属性,都对应着字典当中的key值. //懒加载数据 -(NSMutableArray *)flagArray{ if (_flagArray == nil) { //加载plist 件路径 NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil]; //根据路径从plist文件当中加载数组 NSArray*dictArray =[NSMutableArrayarrayWithContentsOfFile:filePath]; //创建数组 _flagArray = [NSMutableArray array]; for (NSDictionary *dict in dictArray) {//遍历数组当中的每一个元素,数组当中保存的都是字典.
//把字典转成FlagItem模型 FlagItem *item = [FlagItem flagItemDict:dict]; //把模型添加到数组当中 [_flagArray addObject:item]; }} return _flagArray; } 注意:这个地方做了两个初始化,目的是为了不论别人使用这个FlagField是从xib创建,还是从代码创建,都让它做初始化. //从xib当中创建 -(void)awakeFromNib{ //初始化.[self setUp]; } //从代码创建 - (instancetype)initWithFrame:(CGRect)frame{if (self = [super initWithFrame:frame]) {//初始化.[self setUp];}return self; }//初始化. - (void)setUp{ //创建UIPickerView UIPickerView *pick = [[UIPickerView alloc] init]; //设置代理 pick.delegate = self; //设置数据源 pick.dataSource = self;self.inputView = pick; }//数据源方法 //总共有多少列. -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{ return 1; }//总共有多少行 -(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{ 看数组当中有多少个模型,就有多少行. return self.flagArray.count; } //设置每一行的高度 -(CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{ 这个 度就是xib当中描述的View的 度 return 90; } 返回每一行的控件.这里的控件是一个UIView.通过Xib描述的模型. -(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:( //快速创建一个FlagView FlagView *flagV = [FlagView flagView]; //取出当前行对应的模型 FlagItem *item = self.flagArray[row]; 把模型赋值给FlagView的item属性,就会调用FlagItem的set方法,在set方法当中给FlagItem当中的子控件进行赋值. flagV.flagItem = item; 返回FlagView视图. return flagV; }- 执行过程:
05-KVC模型改进- 定义国旗键盘
在给 FlagView成员属性赋值的时候,发现在这里还得要自己去写UIImage, 手动去创建UIImage ,一般在模型当中保存的就是控件最想要的东西.那个这个地方,我们最好在模型当中提供的是一张图片.
-(void)setFlagItem:(FlagItem *)flagItem{ _flagItem = flagItem; //给属性赋值. //设置名称 self.name.text = flagItem.name; //设置图片. self.imageV.image = [UIImage imageNamed:flagItem.icon]; }
所以在这里进行改进模型,让模型当中存放的就是用户最想要的东西. 改过之后会导致一个问题,在KVC给属性赋值的时候,字典当中给的是一个字符串.这样在转的过程当中就会造成类型不匹配,发生错误.
这个时候我们就要看下KVC的底层实现原理,看过后,然后通过它的特性,去避免这个问题
这个是最初的字典转模型的方法.
+(instancetype)flagItemDict:(NSDictionary *)dict{ //创建对象 FlagItem *item = [[self alloc] init]; //通过KVC给对象的属性赋值. [item setValuesForKeysWithDictionary:dict]; //返回 个赋值好属性的对象. return item; }//通过KVC,调用对象的[item setValuesForKeysWithDictionary:dict] setValuesForKeysWithDictionary:底层实现就是
遍历字典当中的所有Key和Value值.给对应的key,value赋值 [dictenumerateKeysAndObjectsUsingBlock:^(id _Nonnullkey,id _Nonnull obj, BOOL * _Nonnull stop) { //给对应的key,value赋值 [item setValue:obj forKeyPath:key]; }];setValue:forKeyPath:的底层实现:
1.它会调用这个属性的set方法. 2.如果没有set方法,它会去判断有没有跟key值同名的成员属性.如果有,就直接赋值,icon = obj. 3.如果没有,那么它还会去判断有没有跟key值名相同带有下划线的成员属性,如果有,就直接赋值,_icon = obj. 4.如果都没有, 就直接报错.找不到对应的成员属性. 利用KVC会调用属性的set方法. 当给icon属性赋值时,把传进来的字符串当作图片的名称,创建一个图片,再给图片进行赋值. 这个的参数,类型是可以改的 - (void)setIcon:(NSString *)icon{UIImage *image = [UIImage imageNamed:icon];_icon = image; }那在View当中就可以直接赋值图片了. -(void)setFlagItem:(FlagItem *)flagItem{_flagItem = flagItem; 给属性赋值.self.name.text = flagItem.name;
//设置名称
//self.imageV.image = [UIImage imageNamed:flagItem.icon]; 模型当中保存的应该是最想的东西,所以在模型当中保存的应该是图片.self.imageV.image = flagItem.icon;//设置图片.
}06-自定义生日键盘
运行示例效果:
-
点击生日时弹出的是一个日期键盘. 实现这种效果采取的方案是自定义一个TextField.修改它的弹出键盘为一个 UIDatePicker.
#import <UIKit/UIKit.h> 注意:这 继承的是UITextField @interface BirthDayField : UITextField @end#import "BirthDayField.h" @implementation BirthDayField 注意:这个地方做了两个初始化,目的是为了不论别人使用这个FlagField是从xib创建,还是从代码创建,都让它做初始化. //从xib当中创建 -(void)awakeFromNib{ //初始化. [self setUp]; }//从代码创建 - (instancetype)initWithFrame:(CGRect)frame{if (self = [super initWithFrame:frame]) {//初始化.[self setUp];}return self; }//初始化方法 - (void)setUp{ //创建UIDatePicker(日期键盘)UIDatePicker *pick = [[UIDatePicker alloc] init]; pick.datePickerMode = UIDatePickerModeDate; ISO639语 编码(中国zh -zhongwen)NSLocale *local = [NSLocale localeWithLocaleIdentifier:@"zh"];pick.locale = local; //UIDatePicker没有代理方法 //监听UIDatePicker的值改变.[pick addTarget:self action:@selector(dateChange:)forControlEvents:UIControlEventValueChanged]; // 定义键盘, 让弹出的键盘是 个UIPickerView.( 定义的键盘是不需要设置尺寸的.)self.inputView = pick; }//当日期改变时调 - (void)dateChange:(UIDatePicker *)datePick{ //把日期转成字符串.NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; //设置日期格式fmt.dateFormat = @"yyyy-MM-dd"; //格式化日期.NSString *dateString = [fmt stringFromDate:datePick.date]; //给日期文本框赋值.self.text = dateString; } @end
07- 定义城市键盘
#import <UIKit/UIKit.h> 注意:这里继承的是UITextField @interface CityTextField : UITextField @end#import "CityTextField.h" 省模型 #import "ProvincesItem.h" @interface CityTextField()<UIPickerViewDataSource,UIPickerViewDelegate> //省份数组.装的都是ProvincesItem模型. @property(nonatomic,strong) NSMutableArray *provincesDataArray; //记录当前选中的是哪一个省份的角标. @property(nonatomic, assign) NSInteger curProIndex; @end
加载数据
数据内容对应的模型图:
数组当中保存的都是字典.我们看到字典就会它转成模型.
所以新建了一个 ProvincesItem模型,ProvincesItem每一个属性,都对应着字典当中的key值.
懒加载省份数据 -(NSMutableArray *)provincesDataArray{ if (_provincesDataArray == nil) { //创建数组 _provincesDataArray = [NSMutableArray array]; //获取plist文件的路径 NSString*filePath= [[NSBundlemainBundle]pathForResource:@"provinces.plist" ofType:nil]; //从plist 文件当中加载数据 NSArray *tempArray = [NSArray arrayWithContentsOfFile:filePath]; //遍历数组当中的每一个元素.每个元素都是一个字典,把字典转成模型 for (NSDictionary *dict in tempArray) { //创建省份模型对象.快速的将字典转成模型 ProvincesItem*item= [ProvincesItemprovincesItemWithDict:dict]; 把转好的对象保存到数组当中. [_provincesDataArray addObject:item]; }} return _provincesDataArray; }-(void)awakeFromNib{ //初始化. [self setUp]; }- (instancetype)initWithFrame:(CGRect)frame{if (self = [super initWithFrame:frame]) { //初始化. [self setUp];} return self; } //初始化方法 - (void)setUp{ //创建UIPickerView UIPickerView *pickV = [[UIPickerView alloc] init]; //设置代理 pickV.delegate = self; //设置数据源. pickV.dataSource = self; //设置弹出键盘是一个UIPickerView self.inputView = pickV; }实现代理协议方法 //总共有多少组 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{ //总共有两组 return 2; } //每组有多少行 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{ //第一组展有多少行,由省份数组决定, 数组当中有多少个省份模型,第一组就有多少行. if (component == 0) {return self.provincesDataArray.count;}else{ //第二组展有多少行,由当前选中的省份决定,当前选中哪个省份.哪个省份下的城市数组决定. 所以要先获取当前先中的是哪个省. ProvincesItem *proItem = self.provincesDataArray[self.curProIndex]; //返回当前省份下城市的个数return proItem.cities.count;} }返回每一行展示的标题 - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{ 如果是第0列,就是省份,返回省份的名称 if (component == 0) { ProvincesItem *proItem = self.provincesDataArray[row]; return proItem.name; }else{ 先取出选中的省份. ProvincesItem *proItem = self.provincesDataArray[self.curProIndex]; //返回选中省份下,每个城市. return proItem.cities[row];} }选中某一列的某一行时会调用这个方法 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)rowinComponent:(NSInteger)component{ //当是第0列的时候.(省份列) if(component == 0){ 记录当前选中的省份的角标 self.curProIndex = row; //刷新列表. [pickerView reloadAllComponents]; //让第1列的第0行成为选中状态.(让城市列每次刷新时,都选中第 0个) [pickerView selectRow:0 inComponent:1 animated:YES]; }//把选中的省份,城市显示到文本框当中. //获取选中的省. ProvincesItem *proItem = self.provincesDataArray[self.curProIndex]; //获取省份的名称 NSString *province = proItem.name; //获取第一列选中的行号.(城市列) NSInteger seleRow = [pickerView selectedRowInComponent:1]; //获取当前选中省下选中的城市名称. NSString *city = proItem.cities[seleRow]; //显示数据 self.text = [NSString stringWithFormat:@"%@ %@",province,city]; }
08- 定义城市键盘(初始化文字处理)
当光标点击文本框的时候,让文本框的文字为第一个自定义键盘选中的文字. 所以监听文本框架的开始编辑的代理 开始编辑时调用,(弹出键盘)became first responder
- (void)textFieldDidBeginEditing:(UITextField *)textField{ }
在这个代理方法当中做事情.每一个文本框当中都提供一个初始化的方法.当在控制器当中调用这个初始化的方法.方法的目的就是让开始编辑选中第一列的第一行.
- (void)initWithText; 国旗键盘初始化方法实现: - (void)initWithText{ [self pickerView:nil didSelectRow:0 inComponent:0]; } //日期键盘初始化方法实现: - (void)initWithText{ [self dateChange:self.pick]; } //城市键盘初始化方法实现: - (void)initWithText{ [self pickerView:self.pick didSelectRow:0 inComponent:0]; }
把方法的参数改成国旗,或者日期,或者城市的类型,改的一个目的是让它能够找到 initWithText 法. 传进来的参数真实类型是什么类型,它就会去调用它真实类型的方法. 如果传进来的键盘类型为日期键盘,它就会调日期的初始化方法.如果真实类型为城市,它就会去调用城市的初始化方法.
- (void)textFieldDidBeginEditing:( FlagField *)textField{ 会去找它真实类型的方法 [textField initWithText]; }
还有一个方法就是在UITextFiled的分类中声明 initWithText 方法,那么在方法 - (void)textFieldDidBeginEditing:( UITextField *)textField{ [textField initWithText]; }
- 补充点:类的加载过程
- 1)在加载类的load方法时,系统会先加载控制器,然后是子类,再是分类,最后才是父类
- 2)在加载类的initialize方法时,系统会先加载控制器,然后是父类,再是分类,最后是子类.
转载于:https://www.cnblogs.com/zhoudaquan/p/5014078.html
UIPickView 和 UIDatePicker相关推荐
- 这个我过滤概述UIPickerView键盘处理
一.介绍UIPickView和UIDatePicker(了解) 1.UIPickView什么时候用? 通常在注册模块,当用户需要选择一些东西的时候,比如说城市,往往弹出一个PickerView给他们选 ...
- 如何弹出UIDatePicker最好
UIDateicker并没有继承UIPickerView,它的宽度只有iphone的宽度,在ipad上直接显示出来非常不协调,所以苹果建议用UIPopoverViewController来显示,所以你 ...
- UIDatePicker | 时间选择器
一:UIDatePicker的介绍 UIDatePicker 是一个控制器类,封装了 UIPickerView,但是他是UIControl的子类,专门用于接受日期.时间和持续时长的输入. 日期选取器的 ...
- iOS基础-UIKit框架-高级视图-UIDatePicker
用处:用在自定义键盘(点击文本框时弹出日期选择.) 一.自定义键盘 先连接TextField -(viewDidLoad){[super viewDidLoad]; //1.创建时间选择器 UIDat ...
- 【IOS 开发】基本 UI 控件详解 (UIDatePicker | UIPickerView | UIStepper | UIWebView | UIToolBar )
转载注明出处 : http://blog.csdn.net/shulianghan/article/details/50348982 一. 日期选择器 (UIDatePicker) UIDatePic ...
- Cocoa touch(十):UIDatePicker
UIDatePicker,日期选取器 typedef NS_ENUM(NSInteger, UIDatePickerMode) {UIDatePickerModeTime, // Displays h ...
- 疯狂ios讲义疯狂连载之日期选择器(UIDatePicker)
UIDatePicker是一个可以用来选择日期和时间的控件.除此之外,它也可作为倒计时控件. 日期选择器(UIDatePicker)继承了UIControl,因此UIDatePicker可以作为活动控 ...
- 利用Runtime修改UIdatePicker的字体颜色
用过苹果原生UIdatePicker的Ios开发者都知道,UIdatePicker这个时间选择器的字体颜色默认的是黑色,并且官方API并没有提供可以修改字体颜色的API.如下: UIDatePicke ...
- UIDatePicker 日期/时间选取器(滚轮)—IOS开发
UIDatePicker 是一个控制器类,封装了 UIPickerView,但是他是UIControl的子类,专门用于接受日期.时间和持续时长的输入.日期选取器的各列会按照指定的风格进行自动配置,这样 ...
最新文章
- jdk javac运行不了_Intellij IDEA搭建jdk源码阅读环境
- 20165101刘天野 2018-2019-2《网络对抗技术》第1周 Kali的安装
- Ceph 存储集群7-故障排除
- python图片比对、自动化测试,腾讯优图及知脸(ZKface)人脸比对接口测试(python)
- [spring]Attribute scope must be declared for element type bean
- 力作推荐!!!! 防线:企业Linux安全运维理念和实战(向世界500强企业学习Linux安全管理与运维之道)...
- 华南理工网络计算机基础知识,2019年华南理工大学网络教育计算机基础随堂练习题第一章.docx...
- 安装office2010出现了错误,提示要安装MSXML6.10.1129.0解决方法
- 支持!解决卡巴斯基程序错误及程序断开的问题!
- 金山词霸2007两个小BUG
- 常见的U盘,内存卡修复工具及其修复方法
- 在宿舍的同学们,只要你有本本,就可以免费无线上网~~
- linux 查看网口实时流速_Linux查看实时带宽流量情况
- CentOS搭建tg的MTProxy代理
- Springcloud微服务中多模块重复代码重构成公共模块的实现
- 小码哥CRM项目(二)p20~p35
- 冯成毅:各类交易者的深度心理剖析
- RGB图灰度及通道理解
- 混合动力汽车用导热电池粘合剂市场现状及未来发展趋势
- 使地方坐标系BIM模型与CAD严格在LSV内对准
热门文章
- Cocos2d-x学习之---关于CCScrollView
- Spring入门(四):使用Maven管理Spring项目
- 2.Elasticsearch插件推荐及安装
- java.sql.SQLException: Can not issue empty query.
- 消除类游戏(js版)
- 问题 C: 判断三角形的性质
- OpenCV-python学习笔记(一)——image basics输入输出,像素处理和绘制图形
- python管道怎么使用_python中管道用法入门实例
- python多继承_Python多继承,__init__
- java 创建存储过程_如何在pl/sql中创建及调用JAVA存储过程 | 学步园