在平时的开发中,经常会用到日期选择器,但如果用的是系统提供的UIDatePicker控件,有时无法满足自己的需求(当然有时觉得丑),所以我们可以通过UIPickerView来自定义一个日期选择器。
下面我写了两个经常会用的日期选择器:
- 通用日期选择器
- 有起始、截止范围的日期选择器(联动日期选择器--实在想不出叫啥名字了。。。)
效果图如下:
通用日期选择器
通用日期选择器.PNG
联动日期选择器
联动日期选择器1.PNG 联动日期选择器2.PNG文件在工程中的位置:
文件.jpg调用方法:
- 通用日期选择器调用方法。若只需默认值,则只需把隐藏的pickerview显示出来即可而无需调用下面的方法(self.pickerView.hidden = NO;)。
/**
配置日期选择器
@param selectedDate 默认选择日期(必须在最大日期和最小日期范围),若nil,则为当前时间
@param dateFormatter 日期格式,若nil,则为yyyy-MM-dd
@param datePickerMode 日期选择器组件类型,默认为SLDatePickerModeDate
*/
- (void)setupPickerViewDataWithDefaultSelectedDate:(NSDate *)selectedDate
dateFormatter:(NSString *)dateFormatter
datePickerMode:(SLDatePickerMode)datePickerMode;
示例代码:
//如果只需要默认值,则屏蔽这行代码
[self.pickerView setupPickerViewDataWithDefaultSelectedDate:[NSDate date] dateFormatter:@"yyyy-MM-dd" datePickerMode:SLDatePickerModeDate];
- 联动日期选择器调用方法
/**
配置日期选择器
@param selectedDate 默认选择日期(必须在最大日期和最小日期范围),若nil,则为当前时间
@param maximumDate 最大日期,若nil,则为[NSDate distantFuture]
@param minimumDate 最小日期,若nil,则为1970-01-01
@param dateFormatter 日期格式,若nil,则为yyyy-MM-dd
@param datePickerMode 日期选择器组件类型,默认为SLDatePickerModeDate
*/
- (void)setupPickerViewDataWithDefaultSelectedDate:(NSDate *)selectedDate
maximumDate:(NSDate *)maximumDate
minimumDate:(NSDate *)minimumDate
dateFormatter:(NSString *)dateFormatter
datePickerMode:(SLDatePickerMode)datePickerMode;
示例代码:
[self.associatedPickerView setupPickerViewDataWithDefaultSelectedDate:[[NSDate date] dateBySubtractingYears:1]
maximumDate:[NSDate date]
minimumDate:[[NSDate date] dateBySubtractingYears:2]
dateFormatter:@"yyyy-MM"
datePickerMode:SLDatePickerModeYearAndMonth];
核心代码实现:
- 通用日期选择器代码实现
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
switch (component) {
case 0: {
self.selectedYear = row % self.yearRows + self.minimumDate.year;
if (SLDatePickerModeYearAndMonth == self.datePickerMode
|| SLDatePickerModeDate == self.datePickerMode) {
[self setSelectedMonth:self.selectedMonth];
if (SLDatePickerModeDate == self.datePickerMode) {
[self setSelectedDay:self.selectedDay];
}
}
}
break;
case 1: {
self.selectedMonth = row % self.monthRows + 1;
if (SLDatePickerModeDate == self.datePickerMode) {
[self setSelectedDay:self.selectedDay];
}
}
break;
case 2: {
self.selectedDay = row % self.dayRows + 1;
}
break;
}
[pickerView reloadAllComponents];
}
#pragma mark - Setter
- (void)setSelectedYear:(NSInteger)selectedYear {
self.yearRows = self.maximumDate.year - self.minimumDate.year + 1;
selectedYear = (selectedYear > self.maximumDate.year) ? self.maximumDate.year : selectedYear;
selectedYear = (selectedYear < self.minimumDate.year) ? self.minimumDate.year : selectedYear;
_selectedYear = selectedYear;
//每次选择都在中间位置附近,保证看似无限滚动的效果
NSInteger selectedRow = ((kMaxNumberOfRows / 2) / self.yearRows) * self.yearRows + _selectedYear - self.minimumDate.year;
if (self.selectedRows.count > 0) {
[self.selectedRows replaceObjectAtIndex:0 withObject:@(selectedRow)];
} else {
[self.selectedRows addObject:@(selectedRow)];
}
[self reloadComponent:0];
[self selectRow:selectedRow inComponent:0 animated:NO];
}
- (void)setSelectedMonth:(NSInteger)selectedMonth {
_selectedMonth = selectedMonth;
self.monthRows = 12;
//每次选择都在中间位置附近,保证看似无限滚动的效果
NSInteger selectedRow = ((kMaxNumberOfRows / 2) / self.monthRows) * self.monthRows + _selectedMonth - 1;
if (self.selectedRows.count > 1) {
[self.selectedRows replaceObjectAtIndex:1 withObject:@(selectedRow)];
} else {
[self.selectedRows addObject:@(selectedRow)];
}
[self reloadComponent:1];
[self selectRow:selectedRow inComponent:1 animated:NO];
}
- (void)setSelectedDay:(NSInteger)selectedDay {
self.dayRows = [NSDate getDaysWithYear:self.selectedYear month:self.selectedMonth];
_selectedDay = (selectedDay > self.dayRows) ? self.dayRows : selectedDay;
//每次选择都在中间位置附近,保证看似无限滚动的效果
NSInteger selectedRow = ((kMaxNumberOfRows / 2) / self.dayRows) * self.dayRows + _selectedDay - 1;
if (self.selectedRows.count > 2) {
[self.selectedRows replaceObjectAtIndex:2 withObject:@(selectedRow)];
} else {
[self.selectedRows addObject:@(selectedRow)];
}
[self reloadComponent:2];
[self selectRow:selectedRow inComponent:2 animated:NO];
}
- 联动日期选择器代码实现
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
switch (component) {
case 0: {
self.selectedYear = row % self.yearRows + self.minimumDate.year;
if (SLDatePickerModeYearAndMonth == self.datePickerMode
|| SLDatePickerModeDate == self.datePickerMode) {
[self setSelectedMonth:self.selectedMonth];
if (SLDatePickerModeDate == self.datePickerMode) {
[self setSelectedDay:self.selectedDay];
}
}
}
break;
case 1: {
if (self.selectedYear == self.minimumDate.year) {
self.selectedMonth = row % self.monthRows + self.minimumDate.month;
} else {
self.selectedMonth = row % self.monthRows + 1;
}
if (SLDatePickerModeDate == self.datePickerMode) {
[self setSelectedDay:self.selectedDay];
}
}
break;
case 2: {
if ([self.maximumDate isSameYearAsDate:self.minimumDate]
&& [self.maximumDate isSameMonthAsDate:self.minimumDate]) {
self.selectedDay = row % self.dayRows + self.minimumDate.day;
} else if (self.selectedYear == self.minimumDate.year) {
if (self.selectedMonth == self.minimumDate.month) {
self.selectedDay = row % self.dayRows + self.minimumDate.day;
} else {
self.selectedDay = row % self.dayRows + 1;
}
} else {
self.selectedDay = row % self.dayRows + 1;
}
}
break;
}
[pickerView reloadAllComponents];
}
#pragma mark - Setter
- (void)setSelectedYear:(NSInteger)selectedYear {
self.yearRows = self.maximumDate.year - self.minimumDate.year + 1;
selectedYear = (selectedYear > self.maximumDate.year) ? self.maximumDate.year : selectedYear;
selectedYear = (selectedYear < self.minimumDate.year) ? self.minimumDate.year : selectedYear;
_selectedYear = selectedYear;
NSInteger selectedRow = (_selectedYear - self.minimumDate.year) % self.yearRows;
if (self.selectedRows.count > 0) {
[self.selectedRows replaceObjectAtIndex:0 withObject:@(selectedRow)];
} else {
[self.selectedRows addObject:@(selectedRow)];
}
[self reloadComponent:0];
[self selectRow:selectedRow inComponent:0 animated:YES];
}
- (void)setSelectedMonth:(NSInteger)selectedMonth {
NSInteger selectedRow = selectedMonth - 1;
if ([self.maximumDate isSameYearAsDate:self.minimumDate]) {
self.monthRows = self.maximumDate.month - self.minimumDate.month + 1;
selectedMonth = (selectedMonth > self.maximumDate.month) ? self.maximumDate.month : selectedMonth;
selectedRow = (selectedMonth - self.minimumDate.month) % self.monthRows;
} else if (self.selectedYear == self.maximumDate.year) {
self.monthRows = self.maximumDate.month;
selectedMonth = (selectedMonth > self.monthRows) ? self.monthRows : selectedMonth;
selectedRow = (selectedMonth - 1) % self.monthRows;
} else if (self.selectedYear == self.minimumDate.year) {
self.monthRows = 12 - self.minimumDate.month + 1;
selectedMonth = (selectedMonth < self.minimumDate.month) ? self.minimumDate.month : selectedMonth;
selectedRow = (selectedMonth - self.minimumDate.month) % self.monthRows;
} else {
self.monthRows = 12;
}
_selectedMonth = selectedMonth;
if (self.selectedRows.count > 1) {
[self.selectedRows replaceObjectAtIndex:1 withObject:@(selectedRow)];
} else {
[self.selectedRows addObject:@(selectedRow)];
}
[self reloadComponent:1];
[self selectRow:selectedRow inComponent:1 animated:YES];
}
- (void)setSelectedDay:(NSInteger)selectedDay {
NSInteger selectedRow = 0;
if ([self.maximumDate isSameYearAsDate:self.minimumDate]
&& [self.maximumDate isSameMonthAsDate:self.minimumDate]) {
self.dayRows = self.maximumDate.day - self.minimumDate.day + 1;
selectedDay = (selectedDay > self.maximumDate.day) ? self.maximumDate.day : selectedDay;
selectedRow = (selectedDay - self.minimumDate.day) % self.dayRows;
} else if (self.selectedYear == self.maximumDate.year) {
if (self.selectedMonth == self.maximumDate.month) {
self.dayRows = self.maximumDate.day;
} else {
self.dayRows = [NSDate getDaysWithYear:self.selectedYear month:self.selectedMonth];
}
selectedDay = (selectedDay > self.dayRows) ? self.dayRows : selectedDay;
selectedRow = (selectedDay - 1) % self.dayRows;
} else if (self.selectedYear == self.minimumDate.year) {
//当前选择年、月下的天数
NSInteger days = [NSDate getDaysWithYear:self.selectedYear month:self.selectedMonth];
if (self.selectedMonth == self.minimumDate.month) {
//需要显示天的行数:(选择月所有天数的和 - 指定最小日期的天数 + 1)。
//例:8月份有31天,若最小天为13号,则该显示的行数为:31 - 13 + 1 = 19行(从13到31)
self.dayRows = days - self.minimumDate.day + 1;
if (selectedDay > days) {//如果选中天数大于当月最大天数
selectedDay = days;
}
selectedDay = (selectedDay < self.minimumDate.day) ? self.minimumDate.day : selectedDay;
selectedRow = (selectedDay - self.minimumDate.day) % self.dayRows;
} else {
self.dayRows = days;
selectedDay = (selectedDay > self.dayRows) ? self.dayRows : selectedDay;
selectedRow = (selectedDay - 1) % self.dayRows;
}
} else {
self.dayRows = [NSDate getDaysWithYear:self.selectedYear month:self.selectedMonth];
selectedDay = (selectedDay > self.dayRows) ? self.dayRows : selectedDay;
selectedRow = (selectedDay - 1) % self.dayRows;
}
_selectedDay = selectedDay;
if (self.selectedRows.count > 2) {
[self.selectedRows replaceObjectAtIndex:2 withObject:@(selectedRow)];
} else {
[self.selectedRows addObject:@(selectedRow)];
}
[self reloadComponent:2];
[self selectRow:selectedRow inComponent:2 animated:YES];
}
好了,代码就贴这么多了,如果有需要的朋友可以到github上面去下载。
里面有部分代码用到 NSDate+Category, 可自行查看。
网友评论