当前位置: 移动技术网 > 移动技术>移动开发>IOS > iOS自定义日期、时间、城市选择器实例代码

iOS自定义日期、时间、城市选择器实例代码

2019年07月24日  | 移动技术网移动技术  | 我要评论

选择器,我想大家都不陌生,当需要用户去选择某些范围值内的一个固定值时,我们会采用选择器的方式。选择器可以直观的提示用户选择的值范围、统一信息的填写格式,同时也方便用户快速的进行选择,比如对于性别,正常情况下就只有男女两种情况,那这时候用一个选择器给用户进行选择的话,可以避免错误数据的输入,也更方便用户去填写。再比如需要获取用户的生日信息时,采用选择器的方式可以统一生日的格式,如果让用户自行输入的话,可能会出现各种各样的生日信息格式,不利于数据的存储,但是采用选择器的方式的话,用户可找到对应的日期进行选择即可。

在ios有专门的一个选择器类uipickerview,进入uipickerview的头文件,我们可以发现 uipickerview直接继承了uiview,其事件处理通过代理方法完成,所以创建uipickerview的时候记得签它的代理uipickerviewdatasourceuipickerviewdelegate。其实它和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地址:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网