iOS自定义日期、时间、城市选择器实例代码
选择器,我想大家都不陌生,当需要用户去选择某些范围值内的一个固定值时,我们会采用选择器的方式。选择器可以直观的提示用户选择的值范围、统一信息的填写格式,同时也方便用户快速的进行选择,比如对于性别,正常情况下就只有男女两种情况,那这时候用一个选择器给用户进行选择的话,可以避免错误数据的输入,也更方便用户去填写。再比如需要获取用户的生日信息时,采用选择器的方式可以统一生日的格式,如果让用户自行输入的话,可能会出现各种各样的生日信息格式,不利于数据的存储,但是采用选择器的方式的话,用户可找到对应的日期进行选择即可。
在ios有专门的一个选择器类uipickerview
,进入uipickerview的头文件,我们可以发现 uipickerview直接继承了uiview,其事件处理通过代理方法完成,所以创建uipickerview的时候记得签它的代理uipickerviewdatasource
和uipickerviewdelegate
。其实它和uitbleview有点像,不过uipickerview还多了个列属性,uitbleview我们都很熟了,所以可以对比uitbleview的相关属性和代理方法来学习记忆uipickerview。
一. uipickerview的代理方法
(1)uipickerviewdatasource对应的代理方法有(其代理方法必须要实现):
返回显示的列数
- (nsinteger)numberofcomponentsinpickerview:(uipickerview *)pickerview;
返回每一列中需要显示的行数
- (nsinteger)pickerview:(uipickerview *)pickerview numberofrowsincomponent:(nsinteger)component;
(2)uipickerviewdelegate对应的代理方法(其代理方法根据需求进行选择性实现):
返回每一列的宽度
- (cgfloat)pickerview:(uipickerview *)pickerview widthforcomponent:(nsinteger)component;
返回每一列的高度
- (cgfloat)pickerview:(uipickerview *)pickerview rowheightforcomponent:(nsinteger)component ;
返回uipickerview控件中指定列的列表项的要显示的内容
- (nullable nsstring *)pickerview:(uipickerview *)pickerview titleforrow:(nsinteger)row forcomponent:(nsinteger)component ;
返回uiview,作为该uipickerview控件中指定列的指定行的显示视图
- (uiview *)pickerview:(uipickerview *)pickerview viewforrow:(nsinteger)row forcomponent:(nsinteger)component reusingview:(nullable uiview *)view ;
选择指定列中的指定行
- (void)pickerview:(uipickerview *)pickerview didselectrow:(nsinteger)row incomponent:(nsinteger)component ;
二、uipickerview和uidatepicker。
uidatepicker是系统帮我们封装好的一个时间日期选择器,继承于uicontrol,uidatepicker有一定的局限性,因为它只有四种显示样式:
uidatepickermodetime, uidatepickermodedate, uidatepickermodedateandtime, uidatepickermodecountdowntimer,
如果需求和这四种样式都不符合的话,那么就没办法使用uidatepicker,比如当只需要显示年、月信息的时候,显然uidatepicker没办法满足我们的需求,那这时我们只能通过uipickerview来自定义自己想要的选择器。
三、uipickerview的自定义使用
(1)创建基类继承于uiview的wxzbasepickview。
我们常见的选择器的样式是一个带透明背景色的view,底部是内容的选择器,有确定和取消按钮,大致如图:
所以我们创建一个基类view,这个view的样式如图所示样式,之后根据内容的差别创建基于该view的选择器。
在.h中声明各个属性及方法
#import <uikit/uikit.h> @interface wxzbasepickview : uiview @property (nonatomic, strong) uiview *contentview; //选择器 @property (nonatomic, strong)uipickerview *pickerview; //取消按钮 @property (nonatomic, strong)uibutton *cancelbutton; //确定按钮 @property (nonatomic, strong)uibutton *confirmbutton; //选择器每一列的高度 @property (nonatomic, assign)cgfloat pickerviewheight; /** * 创建视图,初始化视图时初始数据 */ - (void)initpickview; /** * 确认按钮的点击事件 */ - (void)clickconfirmbutton; /** * pickerview的显示 */ - (void)show; /** * 移除pickerview */ - (void)dismiss; @end
在.m中实现相关方法
#import "wxzbasepickview.h" #define screenwidth [uiscreen mainscreen].bounds.size.width #define screenheight [uiscreen mainscreen].bounds.size.height @implementation wxzbasepickview - (instancetype)init { self = [super init]; if (self) { _pickerviewheight = 250; self.bounds = [uiscreen mainscreen].bounds; self.backgroundcolor = [uicolor colorwithred:0 green:0 blue:0 alpha:0.64]; self.layer.opacity = 0.0; uitapgesturerecognizer *tap=[[uitapgesturerecognizer alloc] initwithtarget:self action:@selector(dismiss)]; self.userinteractionenabled = yes; [self addgesturerecognizer:tap]; [self addsubview:self.contentview]; [self.contentview addsubview:self.pickerview]; [self.contentview addsubview:self.cancelbutton]; [self.contentview addsubview:self.confirmbutton]; [self initpickview]; } return self; } //初始化选择器内容,创建子类时需实现该父类方法 -(void)initpickview{ } //点击确定按钮 - (void)clickconfirmbutton { [self dismiss]; } //点击取消按钮 - (void) clickcancelbutton { [self dismiss]; } //显示选择器 - (void)show { [[uiapplication sharedapplication].keywindow addsubview:self]; [self setcenter:[uiapplication sharedapplication].keywindow.center]; [[uiapplication sharedapplication].keywindow bringsubviewtofront:self]; cgrect frame = self.contentview.frame; frame.origin.y -= self.contentview.frame.size.height; [uiview animatewithduration:0.4 delay:0 options:uiviewanimationoptioncurveeaseout animations:^{ [self.layer setopacity:1.0]; self.contentview.frame = frame; } completion:^(bool finished) { }]; } //移除选择器 - (void)dismiss { cgrect frame = self.contentview.frame; frame.origin.y += self.contentview.frame.size.height; [uiview animatewithduration:0.4 delay:0 options:uiviewanimationoptioncurveeaseout animations:^{ [self.layer setopacity:0.0]; self.contentview.frame = frame; } completion:^(bool finished) { [self removefromsuperview]; }]; } //设置选择器的高度 - (void)setpickerviewheight:(cgfloat)pickerviewheight { _pickerviewheight = pickerviewheight; self.contentview.frame = cgrectmake(self.contentview.frame.origin.x, self.contentview.frame.origin.y, self.contentview.frame.size.width, pickerviewheight); } - (uiview *)contentview { if (!_contentview) { _contentview = [[uiview alloc]initwithframe:cgrectmake(0, screenheight, screenwidth, self.pickerviewheight)]; [_contentview setbackgroundcolor:[uicolor whitecolor]]; } return _contentview; } - (uipickerview *)pickerview { if (!_pickerview) { _pickerview = [[uipickerview alloc]initwithframe:cgrectmake(0, 0, self.contentview.frame.size.width, self.contentview.frame.size.height)]; [_pickerview setbackgroundcolor:[uicolor whitecolor]]; } return _pickerview; } - (uibutton *)cancelbutton { if (!_cancelbutton) { _cancelbutton = [[uibutton alloc]initwithframe:cgrectmake(16, 0, 44, 44)]; [_cancelbutton settitle:@"取消" forstate:uicontrolstatenormal]; [_cancelbutton settitlecolor:[uicolor graycolor] forstate:uicontrolstatenormal]; [_cancelbutton.titlelabel setfont:[uifont systemfontofsize:16]]; [_cancelbutton addtarget:self action:@selector(clickcancelbutton) forcontrolevents:uicontroleventtouchupinside]; } return _cancelbutton; } - (uibutton *)confirmbutton { if (!_confirmbutton) { _confirmbutton = [[uibutton alloc]initwithframe:cgrectmake(self.contentview.frame.size.width - self.cancelbutton.frame.size.width - self.cancelbutton.frame.origin.x, self.cancelbutton.frame.origin.y, self.cancelbutton.frame.size.width, self.cancelbutton.frame.size.height)]; [_confirmbutton settitle:@"确定" forstate:uicontrolstatenormal]; [_confirmbutton settitlecolor:[uicolor bluecolor] forstate:uicontrolstatenormal]; [_confirmbutton.titlelabel setfont:[uifont systemfontofsize:16]]; [_confirmbutton addtarget:self action:@selector(clickconfirmbutton) forcontrolevents:uicontroleventtouchupinside]; } return _confirmbutton; } @end
(2)、自定义一个日期选择器,可选择显示年、月或者年、月、日以及是否显示“至今”选项。
创建继承于我们自定义好的wxzbasepickview的日期选择器wxzpickdateview
.h声明相关属性和方法
#import "wxzbasepickview.h" @class wxzbasepickview; //选择器的选择代理方法 @protocol pickerdateviewdelegate<nsobject> - (void)pickerdateview:(wxzbasepickview *)pickerdateview selectyear:(nsinteger)year selectmonth:(nsinteger)month selectday:(nsinteger)day; @end @interface wxzpickdateview : wxzbasepickview @property(nonatomic, weak)id <pickerdateviewdelegate>delegate ; @property(nonatomic, assign)bool isaddyetselect;//是否增加至今的选项 @property(nonatomic, assign)bool isshowday;//是否显示日 //设置默认显示的值 -(void)setdefaulttselectyear:(nsinteger)defaultselectyear defaultselectmonth:(nsinteger)defaultselectmonth defaultselectday:(nsinteger)defaultselectday; @end
.m实现相关方法
#import "wxzpickdateview.h" @interface wxzpickdateview()<uipickerviewdatasource, uipickerviewdelegate> /** 选择的年 */ @property (nonatomic, assign)nsinteger selectyear; /** 选择的月 */ @property (nonatomic, assign)nsinteger selectmonth; /** 选择的日 */ @property (nonatomic, assign)nsinteger selectday; @property (nonatomic, assign)nsinteger currentyear; @property (nonatomic, assign)nsinteger currentmonth; @property (nonatomic, assign)nsinteger currentday; @property (nonatomic, assign)nsinteger defaultyear; @property (nonatomic, assign)nsinteger defaultmonth; @property (nonatomic, assign)nsinteger defaultday; @property (nonatomic, assign)nsinteger minshowyear; @property (nonatomic, assign)nsinteger yearsum; @end @implementation wxzpickdateview - (void)initpickview { [super initpickview]; _minshowyear = 1940;//最小年份 nscalendar *gregorian = [[nscalendar alloc]initwithcalendaridentifier:nscalendaridentifiergregorian]; // 获取当前日期 nsdate* dt = [nsdate date]; // 指定获取指定年、月、日、时、分、秒的信息 unsigned unitflags = nscalendarunityear | nscalendarunitmonth | nscalendarunitday | nscalendarunithour | nscalendarunitminute | nscalendarunitsecond | nscalendarunitweekday; // 获取不同时间字段的信息 nsdatecomponents* comp = [gregorian components: unitflags fromdate:dt]; _yearsum = comp.year-_minshowyear+1; _currentyear=comp.year; _currentmonth=comp.month; _currentday=comp.day; _selectyear = comp.year; _selectmonth = comp.month; _selectday = comp.day; _defaultyear = comp.year; _defaultmonth = comp.month; _defaultday=comp.day; [self.pickerview setdelegate:self]; [self.pickerview setdatasource:self]; } -(void)setdefaulttselectyear:(nsinteger)defaultselectyear defaultselectmonth:(nsinteger)defaultselectmonth defaultselectday:(nsinteger)defaultselectday{ if (defaultselectyear!=0) { _defaultyear=defaultselectyear; } if (defaultselectmonth!=0) { _defaultmonth = defaultselectmonth; } if (defaultselectday!=0) { _defaultday=defaultselectday; } if (defaultselectyear==-1) { _defaultyear=_currentyear+1; _defaultmonth=1; _defaultday=1; } [self.pickerview selectrow:(_defaultyear - _minshowyear) incomponent:0 animated:no]; [self.pickerview reloadcomponent:1]; [self.pickerview selectrow:(_defaultmonth - 1) incomponent:1 animated:no]; if (_isshowday==yes) { [self.pickerview reloadcomponent:2]; [self.pickerview selectrow:_defaultday incomponent:1 animated:no]; } [self refreshpickviewdata]; } -(void)setisaddyetselect:(bool)isaddyetselect{ _isaddyetselect = isaddyetselect; } - (nsinteger)numberofcomponentsinpickerview:(uipickerview *)pickerview { //判断是否要显示日,如果显示则返回3列,反之返回2列 if (_isshowday==yes) { return 3; }else{ return 2; } } - (nsinteger)pickerview:(uipickerview *)pickerview numberofrowsincomponent:(nsinteger)component { if (component == 0) { if (_isaddyetselect==yes) { //显示至今选项的话,需要比总共要显示的年份多返回一行 return self.yearsum+1; }else{ return self.yearsum; } }else if(component == 1) { nsinteger yearselected = [pickerview selectedrowincomponent:0] + self.minshowyear; if (yearselected==_currentyear+1) { //至今选项的时候月份信息不返回 return 0; }else{ return 12; } }else { nsinteger yearselected = [pickerview selectedrowincomponent:0] + self.minshowyear; if (yearselected==_currentyear+1) { //至今选项的时候日信息不返回 return 0; }else{ nsinteger yearselected = [pickerview selectedrowincomponent:0] + self.minshowyear; nsinteger monthselected = [pickerview selectedrowincomponent:1] + 1; return [self getdayswithyear:yearselected month:monthselected]; } } } //根据年、月判断日期天数 - (nsinteger)getdayswithyear:(nsinteger)year month:(nsinteger)month { switch (month) { case 1: return 31; break; case 2: if (year%400==0 || (year%100!=0 && year%4 == 0)) { return 29; }else{ return 28; } break; case 3: return 31; break; case 4: return 30; break; case 5: return 31; break; case 6: return 30; break; case 7: return 31; break; case 8: return 31; break; case 9: return 30; break; case 10: return 31; break; case 11: return 30; break; case 12: return 31; break; default: return 0; break; } } - (cgfloat)pickerview:(uipickerview *)pickerview rowheightforcomponent:(nsinteger)component { //每一行的高度 return 36; } - (void)pickerview:(uipickerview *)pickerview didselectrow:(nsinteger)row incomponent:(nsinteger)component { nsinteger selectyear; nsinteger selectmonth; switch (component) { case 0: [pickerview reloadcomponent:1]; if (_isaddyetselect==yes) { selectyear = row+_minshowyear+1; }else{ selectyear = row+_minshowyear; } if (_isshowday==yes) { [pickerview reloadcomponent:2]; } break; case 1: selectmonth = row+1; if (_isshowday==yes) { [pickerview reloadcomponent:2]; } default: break; } [self refreshpickviewdata]; } - (uiview *)pickerview:(uipickerview *)pickerview viewforrow:(nsinteger)row forcomponent:(nsinteger)component reusingview:(nullable uiview *)view { nsstring *text; if (component == 0) { if (_isaddyetselect==yes) { if (row+_minshowyear==_currentyear+1) { text=@"至今"; }else{ text = [nsstring stringwithformat:@"%zd年", row + _minshowyear]; } }else{ text = [nsstring stringwithformat:@"%zd年", row + _minshowyear]; } }else if (component == 1){ if (_isaddyetselect==yes) { nsinteger yearselected = [pickerview selectedrowincomponent:0] + self.minshowyear; if (yearselected==_currentyear+1) { text = [nsstring stringwithformat:@""]; }else{ text = [nsstring stringwithformat:@"%zd月", row + 1]; } }else{ text = [nsstring stringwithformat:@"%zd月", row + 1]; } }else{ text = [nsstring stringwithformat:@"%zd日", row + 1]; } uilabel *label = [[uilabel alloc]init]; label.textalignment = 1; label.font = [uifont systemfontofsize:16]; label.text = text; return label; } - (void)clickconfirmbutton { if ([self.delegate respondstoselector:@selector(pickerdateview:selectyear:selectmonth:selectday:)]) { [self.delegate pickerdateview:self selectyear:self.selectyear selectmonth:self.selectmonth selectday:self.selectday]; } [super clickconfirmbutton]; } - (void)refreshpickviewdata { self.selectyear = [self.pickerview selectedrowincomponent:0] + self.minshowyear; self.selectmonth = [self.pickerview selectedrowincomponent:1] + 1; if (_isshowday==yes) { self.selectday = [self.pickerview selectedrowincomponent:2] + 1; } } - (void)setyearleast:(nsinteger)yearleast { _minshowyear = yearleast; } - (void)setyearsum:(nsinteger)yearsum { _yearsum = yearsum; } -(void)setisshowday:(bool)isshowday{ _isshowday=isshowday; } @end
(3) 创建继承于wxzbasepickview的时间选择器wxzpicktimeview。
.h声明属性及相关方法
#import "wxzbasepickview.h" @class wxzpicktimeview; @protocol picktimeviewdelegate<nsobject> - (void)pickertimeview:(wxzpicktimeview *)pickertimeview selecthour:(nsinteger)hour selectminute:(nsinteger)minute ; @end @interface wxzpicktimeview : wxzbasepickview @property(nonatomic, weak)id <picktimeviewdelegate>delegate ; -(void)setdefaulthour:(nsinteger)hour defaultminute:(nsinteger)minute ; @end
.m实现相关方法
#import "wxzpicktimeview.h" @interface wxzpicktimeview () <uipickerviewdatasource, uipickerviewdelegate>{ uidatepicker *_datepicker; } @property (nonatomic, assign)nsinteger selecthour; @property (nonatomic, assign)nsinteger selectminute; @property (nonatomic, assign)nsinteger day; @property (nonatomic, assign)nsinteger defaulthour; @property (nonatomic, assign)nsinteger defaultminute; @end @implementation wxzpicktimeview - (void)initpickview { [super initpickview]; nscalendar *gregorian = [[nscalendar alloc] initwithcalendaridentifier:nscalendaridentifiergregorian]; // 获取当前日期 nsdate* dt = [nsdate date]; // 定义一个时间字段的旗标,指定将会获取指定年、月、日、时、分、秒的信息 unsigned unitflags = nscalendarunityear | nscalendarunitmonth | nscalendarunitday | nscalendarunithour | nscalendarunitminute | nscalendarunitsecond | nscalendarunitweekday; // 获取不同时间字段的信息 nsdatecomponents* comp = [gregorian components: unitflags fromdate:dt]; _selecthour=comp.hour; _selectminute=comp.minute; [self.pickerview setdelegate:self]; [self.pickerview setdatasource:self]; [self.pickerview selectrow:_selecthour incomponent:0 animated:no]; [self.pickerview selectrow:_selectminute incomponent:1 animated:no]; } -(void)setdefaulthour:(nsinteger)hour defaultminute:(nsinteger)minute{ if (hour!=0) { _defaulthour=hour; }else{ _defaulthour=_selecthour; } if (minute!=0) { _defaultminute = minute; }else{ _defaultminute=_selectminute; } [self.pickerview selectrow:_defaulthour incomponent:0 animated:no]; [self.pickerview reloadcomponent:1]; [self.pickerview selectrow:_defaultminute incomponent:1 animated:no]; [self refreshpicktimeviewdata]; } - (nsinteger)numberofcomponentsinpickerview:(uipickerview *)pickerview { return 2; } - (nsinteger)pickerview:(uipickerview *)pickerview numberofrowsincomponent:(nsinteger)component { if (component == 0) { return 24; }else { return 60; } } - (cgfloat)pickerview:(uipickerview *)pickerview rowheightforcomponent:(nsinteger)component { return 36; } - (void)pickerview:(uipickerview *)pickerview didselectrow:(nsinteger)row incomponent:(nsinteger)component { switch (component) { case 0: [pickerview reloadcomponent:1]; break; case 1: default: break; } [self refreshpicktimeviewdata]; } - (uiview *)pickerview:(uipickerview *)pickerview viewforrow:(nsinteger)row forcomponent:(nsinteger)component reusingview:(nullable uiview *)view { nsstring *text; if (component == 0) { if (row<10) { text = [nsstring stringwithformat:@"0%zd时", row]; }else{ text = [nsstring stringwithformat:@"%zd时", row]; } }else if (component == 1){ if (row<10) { text = [nsstring stringwithformat:@"0%zd分", row ]; }else{ text = [nsstring stringwithformat:@"%zd分", row ]; } }else{ } uilabel *label = [[uilabel alloc]init]; label.textalignment = 1; label.font = [uifont systemfontofsize:16]; label.text = text; return label; } - (void)clickconfirmbutton { if ([self.delegate respondstoselector:@selector(pickertimeview:selecthour:selectminute:)]) { [self.delegate pickertimeview:self selecthour:self.selecthour selectminute:self.selectminute]; } [super clickconfirmbutton]; } - (void)refreshpicktimeviewdata { self.selecthour = [self.pickerview selectedrowincomponent:0]; self.selectminute = [self.pickerview selectedrowincomponent:1]; } @end
(4)创建继承于wxzbasepickview的城市选择器wxzpickcityview。
.h声明相关属性和方法
#import "wxzbasepickview.h" @class wxzpickcityview; @protocol pickercityviewdelegate<nsobject> - (void)pickerarea:(wxzpickcityview *)pickerarea selectprovince:(nsstring *)province selectcity:(nsstring *)city; @end @interface wxzpickcityview : wxzbasepickview @property(nonatomic, weak)id <pickercityviewdelegate>delegate ; /**设置默认的省市*/ -(void)setdefaultcity:(nsstring *)defaultcity defaultprovience:(nsstring *)defaultprovience; @end
.m实现相关方法
#import "wxzpickcityview.h" @interface wxzpickcityview()<uipickerviewdatasource, uipickerviewdelegate> @property (nonatomic, strong, nullable)nsarray *areadatasource; @property (nonatomic, strong, nullable)nsmutablearray *provincearray; @property (nonatomic, strong, nullable)nsmutablearray *cityarray; @property (nonatomic, strong, nullable)nsmutablearray *selectedarray;//当前选中的数组 @property (nonatomic, strong, nullable)nsstring *selectprovince; @property (nonatomic, strong, nullable)nsstring *selectcity; @end @implementation wxzpickcityview - (void)initpickview { [super initpickview]; for (nsdictionary *dic in self.areadatasource) { [self.provincearray addobject:dic[@"state"]]; } nsmutablearray *citysarr = [nsmutablearray arraywitharray:[self.areadatasource firstobject][@"cities"]]; for (nsdictionary *dic in citysarr) { [self.cityarray addobject:dic[@"city"]]; } self.selectprovince = self.provincearray[0]; self.selectcity = self.cityarray[0]; [self.pickerview setdelegate:self]; [self.pickerview setdatasource:self]; } //设置默认显示的省市 -(void)setdefaultcity:(nsstring *)defaultcity defaultprovience:(nsstring *)defaultprovience{ for (nsinteger i = 0; i<_provincearray.count; i++) { if ([_provincearray[i] isequaltostring:defaultprovience]) { [self.pickerview selectrow:i incomponent:0 animated:no]; self.selectedarray = self.areadatasource[i][@"cities"]; [self.cityarray removeallobjects]; [self.selectedarray enumerateobjectsusingblock:^(nsdictionary *obj, nsuinteger idx, bool * _nonnull stop) { [self.cityarray addobject:obj[@"city"]]; }]; for (nsinteger j= 0; j<_cityarray.count; j++) { if ([defaultcity isequaltostring:_cityarray[j]]) { [self.pickerview selectrow:i incomponent:0 animated:no]; [self.pickerview reloadcomponent:1]; [self.pickerview selectrow:j incomponent:1 animated:no]; [self refreshselectareadata]; } } } } } - (nsinteger)numberofcomponentsinpickerview:(uipickerview *)pickerview { return 2; } - (nsinteger)pickerview:(uipickerview *)pickerview numberofrowsincomponent:(nsinteger)component { if (component == 0) { return self.provincearray.count; }else { return self.cityarray.count; } } - (cgfloat)pickerview:(uipickerview *)pickerview rowheightforcomponent:(nsinteger)component { return 36; } - (void)pickerview:(uipickerview *)pickerview didselectrow:(nsinteger)row incomponent:(nsinteger)component { if (component == 0) { self.selectedarray = self.areadatasource[row][@"cities"]; [self.cityarray removeallobjects]; [self.selectedarray enumerateobjectsusingblock:^(nsdictionary *obj, nsuinteger idx, bool * _nonnull stop) { [self.cityarray addobject:obj[@"city"]]; }]; [pickerview reloadcomponent:1]; [pickerview selectrow:0 incomponent:1 animated:yes]; }else if (component == 1) { if (self.selectedarray.count == 0) { self.selectedarray = [self.areadatasource firstobject][@"cities"]; } }else{ } [self refreshselectareadata]; } - (uiview *)pickerview:(uipickerview *)pickerview viewforrow:(nsinteger)row forcomponent:(nsinteger)component reusingview:(nullable uiview *)view { for(uiview *singleline in pickerview.subviews) { if (singleline.frame.size.height < 1) { singleline.backgroundcolor =[uicolor graycolor]; } } nsstring *text; if (component == 0) { text = self.provincearray[row]; }else if (component == 1){ text = self.cityarray[row]; }else{ } uilabel *label = [[uilabel alloc]init]; label.textalignment = 1; label.font = [uifont systemfontofsize:16]; label.text = text; return label; } - (void)clickconfirmbutton { [self.delegate pickerarea:self selectprovince:self.selectprovince selectcity:self.selectcity]; [super clickconfirmbutton]; } - (void)refreshselectareadata { nsinteger provienceindex = [self.pickerview selectedrowincomponent:0]; nsinteger cityindex = [self.pickerview selectedrowincomponent:1]; self.selectprovince = self.provincearray[provienceindex]; self.selectcity = self.cityarray[cityindex]; } - (nsarray *)areadatasource { if (!_areadatasource) { nsstring *path = [[nsbundle bundleforclass:[wxzpickcityview class]] pathforresource:@"area" oftype:@"plist"]; _areadatasource = [[nsarray alloc]initwithcontentsoffile:path]; } return _areadatasource; } - (nsmutablearray *)provincearray { if (!_provincearray) { _provincearray = [nsmutablearray array]; } return _provincearray; } - (nsmutablearray *)cityarray { if (!_cityarray) { _cityarray = [nsmutablearray array]; } return _cityarray; } - (nsmutablearray *)selectedarray { if (!_selectedarray) { _selectedarray = [nsmutablearray array]; } return _selectedarray; } @end
(5)创建继承于wxzbasepickview的单列选择器wxzcustompickview,可根据传进来的数组显示相关的选择内容
.h声明相关属性和方法
#import "wxzbasepickview.h" @class wxzcustompickview; @protocol custompickviewdelegate<nsobject> - (void)custompickview:(wxzcustompickview *)custompickview selectedtitle:(nsstring *)selectedtitle; @end @interface wxzcustompickview :wxzbasepickview @property (nonatomic, strong)nsmutablearray *dataarray; @property(nonatomic, copy)nsstring *defalutselectrowstr; @property(nonatomic, weak)id <custompickviewdelegate>delegate; @end
.m实现相关方法
#import "wxzcustompickview.h" @interface wxzcustompickview()<uipickerviewdatasource, uipickerviewdelegate> /** 1.选中的字符串 */ @property (nonatomic, strong, nullable)nsstring *selectedtitle; @end @implementation wxzcustompickview - (void)initpickview { [super initpickview]; _dataarray=[nsmutablearray mutablecopy]; [self.pickerview setdelegate:self]; [self.pickerview setdatasource:self]; } -(void)setdefalutselectrowstr:(nsstring *)defalutselectrowstr{ _defalutselectrowstr=defalutselectrowstr; for (nsinteger i = 0; i<_dataarray.count; i++) { if ([_dataarray[i] isequaltostring:_defalutselectrowstr]) { [self.pickerview reloadallcomponents]; [self.pickerview selectrow:i incomponent:0 animated:no]; } } } - (nsinteger)numberofcomponentsinpickerview:(uipickerview *)pickerview { return 1; } - (nsinteger)pickerview:(uipickerview *)pickerview numberofrowsincomponent:(nsinteger)component { return self.dataarray.count; } - (cgfloat)pickerview:(uipickerview *)pickerview rowheightforcomponent:(nsinteger)component { return 36; } - (cgfloat)pickerview:(uipickerview *)pickerview widthforcomponent:(nsinteger)component { return self.frame.size.width; } - (void)pickerview:(uipickerview *)pickerview didselectrow:(nsinteger)row incomponent:(nsinteger)component { self.selectedtitle = self.dataarray[row]; } - (uiview *)pickerview:(uipickerview *)pickerview viewforrow:(nsinteger)row forcomponent:(nsinteger)component reusingview:(nullable uiview *)view { for(uiview *singleline in pickerview.subviews) { if (singleline.frame.size.height < 1) { singleline.backgroundcolor =[uicolor graycolor]; } } uilabel *label = [[uilabel alloc]init]; label.font=[uifont systemfontofsize:16]; label.textalignment = 1; label.text=self.dataarray[row]; return label; } #pragma mark -点击确定按钮 - (void)clickconfirmbutton { [self.delegate custompickview:self selectedtitle:self.selectedtitle]; [super clickconfirmbutton]; } - (void)setdataarray:(nsmutablearray *)dataarray { _dataarray = dataarray; _selectedtitle = dataarray.firstobject; [self.pickerview reloadallcomponents]; } @end
这样,几种类型的选择器我们都定义好了,在需要选择器的地方,根据需求创建相应的选择器即可。
四、如何使用已创建好的自定义选择器
引入自定义好的选择器,声明相关属性,签相关协议
#import "viewcontroller.h" #import "wxzpickdateview.h" #import "wxzpickareaview.h" #import "wxzpicktimeview.h" #import "wxzcustompickview.h" @interface viewcontroller ()<pickerdateviewdelegate,pickerareaviewdelegate,picktimeviewdelegate,custompickviewdelegate>{ uibutton *datebutton; uibutton *selectareabutton; uibutton *selecttimebutton; uibutton *singlepickviewselectbutton; bool isshowday;//是否显示日信息 } @end
创建相应的按钮,触发相应的选择器
- (void)viewdidload { [super viewdidload]; datebutton=[uibutton buttonwithtype:uibuttontypecustom]; datebutton.frame=cgrectmake(100, 100, 100, 50); [datebutton settitle:@"选择日期" forstate:uicontrolstatenormal]; [self.view addsubview:datebutton]; [datebutton settitlecolor:[uicolor blackcolor] forstate:uicontrolstatenormal]; [datebutton addtarget:self action:@selector(pickviewselect:) forcontrolevents:uicontroleventtouchupinside]; datebutton.tag = 1000; selectareabutton=[uibutton buttonwithtype:uibuttontypecustom]; selectareabutton.frame=cgrectmake(100, 200, 100, 50); [selectareabutton settitle:@"选择地区" forstate:uicontrolstatenormal]; [self.view addsubview:selectareabutton]; [selectareabutton settitlecolor:[uicolor blackcolor] forstate:uicontrolstatenormal]; [selectareabutton addtarget:self action:@selector(pickviewselect:) forcontrolevents:uicontroleventtouchupinside]; selectareabutton.tag = 1001; selecttimebutton=[uibutton buttonwithtype:uibuttontypecustom]; selecttimebutton.frame=cgrectmake(100, 300, 100, 50); [selecttimebutton settitle:@"选择时间" forstate:uicontrolstatenormal]; [self.view addsubview:selecttimebutton]; [selecttimebutton settitlecolor:[uicolor blackcolor] forstate:uicontrolstatenormal]; [selecttimebutton addtarget:self action:@selector(pickviewselect:) forcontrolevents:uicontroleventtouchupinside]; selecttimebutton.tag = 1002; singlepickviewselectbutton=[uibutton buttonwithtype:uibuttontypecustom]; singlepickviewselectbutton.frame=cgrectmake(100, 400, 100, 50); [singlepickviewselectbutton settitle:@"单个数据选择器" forstate:uicontrolstatenormal]; [self.view addsubview:singlepickviewselectbutton]; [singlepickviewselectbutton settitlecolor:[uicolor blackcolor] forstate:uicontrolstatenormal]; [singlepickviewselectbutton addtarget:self action:@selector(pickviewselect:) forcontrolevents:uicontroleventtouchupinside]; singlepickviewselectbutton.tag = 1003; }
按钮的点击事件:
-(void)pickviewselect:(uibutton *)button{ if (button.tag==1000) { wxzpickdateview *pickerdate = [[wxzpickdateview alloc]init]; [pickerdate setisaddyetselect:yes];//是否显示至今选项 [pickerdate setisshowday:yes];//是否显示日信息 [pickerdate setdefaulttselectyear:2007 defaultselectmonth:4 defaultselectday:1];//设定默认显示的日期 [pickerdate setvalidtime:2010]; [pickerdate setdelegate:self]; [pickerdate show]; }else if (button.tag==1001){ wxzpickareaview *pickerarea = [[wxzpickareaview alloc]init]; [pickerarea setdelegate:self]; [pickerarea setdefaultcity:@"上海" defaultprovience:@"上海"]; [pickerarea show]; [self.view endediting:yes]; }else if (button.tag==1002){ wxzpicktimeview *pickerarea = [[wxzpicktimeview alloc]init]; [pickerarea setdelegate:self]; [pickerarea setdefaulthour:14 defaultminute:20]; [pickerarea show]; [self.view endediting:yes]; }else{ nsmutablearray *arraydata = [nsmutablearray arraywithobjects:@"2k以下",@"2k-5k",@"5k-10k",@"10k-15k",@"15k-25k",@"25k-50k",@"50k以上", nil]; wxzcustompickview *pickersingle = [[wxzcustompickview alloc]init]; [pickersingle setdataarray:arraydata]; [pickersingle setdefalutselectrowstr:arraydata[0]]; [pickersingle setdelegate:self]; [pickersingle show]; [self.view endediting:yes]; } }
选择器的代理方法
-(void)pickerdateview:(wxzbasepickview *)pickerdateview selectyear:(nsinteger)year selectmonth:(nsinteger)month selectday:(nsinteger)day{ nslog(@"选择的日期是:%ld %ld %ld",year,month,day); if (isshowday==yes) { [datebutton settitle:[nsstring stringwithformat:@"%ld年 %ld月 %ld日",year,month,day] forstate:uicontrolstatenormal]; }else{ [datebutton settitle:[nsstring stringwithformat:@"%ld年 %ld月",year,month] forstate:uicontrolstatenormal]; } } -(void)pickerarea:(wxzpickareaview *)pickerarea selectprovince:(nsstring *)province selectcity:(nsstring *)city{ nslog(@"省市的选择%@ %@",province,city); [selectareabutton settitle:[nsstring stringwithformat:@"%@%@",province,city] forstate:uicontrolstatenormal]; } -(void)custompickview:(wxzcustompickview *)custompickview selectedtitle:(nsstring *)selectedtitle{ nslog(@"选择%@",selectedtitle); [singlepickviewselectbutton settitle:selectedtitle forstate:uicontrolstatenormal]; } -(void)pickertimeview:(wxzpicktimeview *)pickertimeview selecthour:(nsinteger)hour selectminute:(nsinteger)minute{ nslog(@"选择的时间:%ld %ld",hour,minute); [selecttimebutton settitle:[nsstring stringwithformat:@"%ld时 %ld分",hour,minute] forstate:uicontrolstatenormal]; }
最后,看看效果图:
有需要的可以下载demo看看
github地址:https://github.com/wxzwork/custompickview
demo地址:custompickview_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。