美文网首页
iOS 自定义日期选择器datePickerview

iOS 自定义日期选择器datePickerview

作者: WSonglin | 来源:发表于2018-08-15 13:37 被阅读0次

    在平时的开发中,经常会用到日期选择器,但如果用的是系统提供的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, 可自行查看。

    文章 Demo

    相关文章

      网友评论

          本文标题:iOS 自定义日期选择器datePickerview

          本文链接:https://www.haomeiwen.com/subject/teiibftx.html