選擇器,我想大家都不陌生,當需要用戶去選擇某些范圍值內的一個固定值時,我們會采用選擇器的方式。選擇器可以直觀的提示用戶選擇的值范圍、統一信息的填寫格式,同時也方便用戶快速的進行選擇,比如對於性別,正常情況下就只有男女兩種情況,那這時候用一個選擇器給用戶進行選擇的話,可以避免錯誤數據的輸入,也更方便用戶去填寫。再比如需要獲取用戶的生日信息時,采用選擇器的方式可以統一生日的格式,如果讓用戶自行輸入的話,可能會出現各種各樣的生日信息格式,不利於數據的存儲,但是采用選擇器的方式的話,用戶可找到對應的日期進行選擇即可。
在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
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。