美文网首页
iOS 年月日时间区间选择器

iOS 年月日时间区间选择器

作者: 邓布利多教授 | 来源:发表于2019-06-22 18:12 被阅读0次

    1、创建一个集成PickerView的View

    .h文件

    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @protocol LYDateIntervalSelectorPickerDelegate <NSObject>
    
    -(void)dateWithSelect:(NSDate *)date;
    
    @end
    
    @interface LYDateIntervalSelectorPicker : UIPickerView<UIPickerViewDelegate, UIPickerViewDataSource>
    
    -(instancetype)initWithDatePickerView;
    
    @property (nonatomic, assign) id<LYDateIntervalSelectorPickerDelegate> pvDelegate;
    
    @property (nonatomic, strong, readonly) NSDate *date;
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    .m文件

    #import "LYDateIntervalSelectorPicker.h"
    
    static CGFloat rowsHeight = 44.0;
    
    @interface LYDateIntervalSelectorPicker ()
    
    @property (nonatomic, strong) NSIndexPath *todayIndexPath;
    @property (nonatomic, strong) NSArray *months;
    @property (nonatomic, strong) NSArray *years;
    @property (nonatomic, strong) NSArray *days;
    @property (nonatomic, strong) NSCalendar *calendar;
    
    @end
    
    @implementation LYDateIntervalSelectorPicker
    
    -(instancetype)initWithDatePickerView{
        
        self = [super init];
        if (self) {
            
            self.delegate = self;
            self.dataSource = self;
            
            self.years = [self nameOfYears];
            self.months = [self nameOfMonths];
            self.days = [self nameOfDays];
            self.todayIndexPath = [self todayPath];
            [self selectCurrentDate];
            
        }
        return self;
        
    }
    
    - (void)selectCurrentDate{
        
        NSIndexPath *selectIndexPath = [self todayPath];
        
        //设置当前年份
        [self selectRow:selectIndexPath.section
            inComponent:0
               animated:YES];
        [self pickerView:self didSelectRow:selectIndexPath.row inComponent:0];
        
        selectIndexPath = [self todayPath];
        
        //设置当前月份
        [self selectRow:selectIndexPath.row
            inComponent:1
               animated:YES];
        [self pickerView:self didSelectRow:selectIndexPath.row inComponent:1];
        
        //设置当前日期
        CGFloat day = [[[self currentDayName] substringToIndex:[self currentDayName].length] floatValue] - 1;
        [self selectRow:day inComponent:2 animated:YES];
        [self pickerView:self didSelectRow:day inComponent:2];
        
    }
    
    - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
        
        //获取当前选中的是几号
        NSInteger currert = [pickerView selectedRowInComponent:2] + 1;
        
        //判断二月份最大天数和30号和31号
        if (currert > [self daysCountWithSelectDate]) {
            [pickerView selectRow:[self daysCountWithSelectDate] inComponent:2 animated:NO];
        }
        
        if (component == 0 || component == 1) {
            self.days = [self nameOfDays];
            [pickerView reloadComponent:1];
            [pickerView reloadComponent:2];
        }
        
        if ([self.pvDelegate respondsToSelector:@selector(dateWithSelect:)]) {
            [self.pvDelegate dateWithSelect:[self date]];
        }
        
    }
    
    -(NSDate *)date{
    
        NSString *year = [self.years objectAtIndex:([self selectedRowInComponent:0])];
        NSString *month = [self.months objectAtIndex:([self selectedRowInComponent:1])];
        NSString *day = [self.days objectAtIndex:([self selectedRowInComponent:2]) % self.days.count];
    
        NSDateFormatter *formatter = [NSDateFormatter new];
        [formatter setDateFormat:@"yyyy年M月d日"];
        NSString *dateString = [NSString stringWithFormat:@"%@%@%@", year, month, day];
        NSDate *date = [formatter dateFromString:dateString];
        return date;
    
    }
    
    #pragma mark - UIPickerViewDelegate
    
    -(CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{
        return [self componentWidth];
    }
    
    -(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
    
        UILabel *returnView = [self labelForComponent:component];
        returnView.text = [self titleForRow:row forComponent:component];
        return returnView;
        
    }
    
    -(CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
        return rowsHeight;
    }
    
    #pragma mark - UIPickerViewDataSource
    - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
        return 3;
    }
    
    -(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
        
        if(component == 0){
            return self.years.count;
        }else if (component == 1) {
            return self.months.count;
        }else {
            return self.days.count;
        }
        
    }
    
    -(CGFloat)componentWidth{
        return self.bounds.size.width / 3;
    }
    
    -(NSString *)titleForRow:(NSInteger)row forComponent:(NSInteger)component{
        
        if(component == 0) {
            return [self.years objectAtIndex:(row)];
        }else if(component == 1) {
            return [self.months objectAtIndex:(row)];
        }else {
            NSInteger DayCount = self.days.count;
            return [self.days objectAtIndex:(row % DayCount)];
        }
        
    }
    
    -(UILabel *)labelForComponent:(NSInteger)component{
        
        CGRect frame = CGRectMake(0, 0, [self componentWidth], rowsHeight);
        UILabel *label = [[UILabel alloc] initWithFrame:frame];
        label.textAlignment = NSTextAlignmentCenter;
        label.backgroundColor = [UIColor clearColor];
        label.userInteractionEnabled = NO;
        return label;
        
    }
    
    
    
    #pragma mark --------- 华丽的分割线 ---------
    
    
    
    //当前时间
    -(NSIndexPath *)todayPath{
        
        CGFloat row = 0.f;
        CGFloat section = 0.f;
        
        NSString *year  = [self currentYearName];
        NSString *month = [self currentMonthName];
        
        for(NSString *cellYear in self.years) {
            
            if([cellYear isEqualToString:year]) {
                section = [self.years indexOfObject:cellYear];
                break;
            }
            
        }
        
        for(NSString *cellMonth in self.months) {
            
            if([cellMonth isEqualToString:month]) {
                row = [self.months indexOfObject:cellMonth];
                break;
            }
            
        }
        
        return [NSIndexPath indexPathForRow:row inSection:section];
        
    }
    
    //年份数组
    -(NSArray *)nameOfYears{
        
        NSMutableArray *years = [NSMutableArray array];
        NSInteger currentYear = [[[self currentYearName] substringToIndex:4] integerValue];
        
        for(NSInteger year = currentYear - 5; year <= currentYear; year++) {
            NSString *yearStr = [NSString stringWithFormat:@"%li年", (long)year];
            [years addObject:yearStr];
        }
        return years;
        
    }
    
    //月份数组
    -(NSArray *)nameOfMonths{
        return @[@"1月", @"2月", @"3月", @"4月", @"5月", @"6月", @"7月", @"8月", @"9月", @"10月", @"11月", @"12月"];
    }
    
    //日期数组
    -(NSArray *)nameOfDays{
        
        NSUInteger numberOfDaysInMonth = [self daysCountWithSelectDate];
        NSMutableArray *tempArr = [NSMutableArray array];
        for (int i = 1; i < numberOfDaysInMonth + 1 ; i ++) {
            NSString *day = [NSString stringWithFormat:@"%d日",i];
            [tempArr addObject:day];
        }
        return tempArr;
        
    }
    
    //根据当前年月获取当前月天数
    -(NSInteger)daysCountWithSelectDate{
        self.calendar = [NSCalendar currentCalendar];
        NSRange range = [self.calendar rangeOfUnit:NSCalendarUnitDay
                                            inUnit:NSCalendarUnitMonth
                                           forDate:[self monthDate]];
        return range.length;
    }
    
    //根据当前年月返回日期
    -(NSDate *)monthDate{
        
        NSString *year = [self.years objectAtIndex:([self selectedRowInComponent:0])];
        NSString *month = [self.months objectAtIndex:([self selectedRowInComponent:1])];
        NSDateFormatter *formatter = [NSDateFormatter new];
        [formatter setDateFormat:@"yyyy年M月"];
        NSDate *date = [formatter dateFromString:[NSString stringWithFormat:@"%@%@", year, month]];
        return date;
        
    }
    
    //当前年份
    -(NSString *)currentYearName{
        
        NSDateFormatter *formatter = [NSDateFormatter new];
        [formatter setDateFormat:@"yyyy年"];
        return [formatter stringFromDate:[NSDate date]];
        
    }
    
    //当前月份
    -(NSString *)currentMonthName{
        
        NSDateFormatter *formatter = [NSDateFormatter new];
        NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
        [formatter setLocale:usLocale];
        [formatter setDateFormat:@"M月"];
        return [formatter stringFromDate:[NSDate date]];
        
    }
    
    //当前日期
    -(NSString *)currentDayName{
        
        NSDateFormatter *formatter = [NSDateFormatter new];
        [formatter setDateFormat:@"d日"];
        return [formatter stringFromDate:[NSDate date]];
        
    }
    
    @end
    

    2、创建一个View

    .h文件

    #import <UIKit/UIKit.h>
    #import "LYDateIntervalSelectorPicker.h"
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface LYDateIntervalSelectorView : UIView
    
    //单例
    +(LYDateIntervalSelectorView *)initClient;
    
    -(void)datePickerCompleteBlock:(void (^)(NSDate *startDate, NSDate *endDate))completeBlock;
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    .m文件 — 引入头文件
    #import "LYDateIntervalSelectorPicker.h"

    #import "LYDateIntervalSelectorView.h"
    #import "LYDateIntervalSelectorPicker.h"
    
    static CGFloat whiteViewHeight = 400.f;
    static CGFloat pickerHeight = 250.f;
    
    //时间回调
    typedef void (^ DateBlock)(NSDate *, NSDate *);
    
    @interface LYDateIntervalSelectorView ()<LYDateIntervalSelectorPickerDelegate>
    {
        CGFloat height;
        CGFloat width;
    }
    
    //白色背景
    @property (nonatomic, strong) UIView *whiteView;
    
    @property (nonatomic, copy) DateBlock dateBlock;
    
    //开始时间
    @property (nonatomic, strong) UIButton *bStart;
    //结束时间
    @property (nonatomic, strong) UIButton *bEnd;
    
    //开始时间date
    @property (nonatomic, strong) NSDate *startDate;
    //结束时间date
    @property (nonatomic, strong) NSDate *endDate;
    
    //选择器
    @property (nonatomic, strong) LYDateIntervalSelectorPicker *selectorPicker;
    
    //区分当前操作时间——开始时间或结束时间
    @property (nonatomic) BOOL timeType;
    
    @end
    
    @implementation LYDateIntervalSelectorView
    
    +(LYDateIntervalSelectorView *)initClient{
        
        static LYDateIntervalSelectorView *client = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            client = [[self alloc] initWithFrame:[UIScreen mainScreen].bounds];
            [client createUI];
        });
        return client;
        
    }
    
    -(void)datePickerCompleteBlock:(void (^)(NSDate *startDate, NSDate *endDate))completeBlock{
        
        _dateBlock = completeBlock;
        [self show];
        
    }
    
    #pragma mark - 创建布局
    -(void)createUI{
        
        height = [UIScreen mainScreen].bounds.size.height;
        width = [UIScreen mainScreen].bounds.size.width;
        
        //默认时间
        self.endDate = [NSDate date];
        self.startDate = [NSDate date];
        
        //取消手势
        UITapGestureRecognizer *cancelTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapCancelAction)];
        [self addGestureRecognizer:cancelTap];
        
        //白色背景
        self.whiteView = [[UIView alloc]initWithFrame:CGRectMake(0, height, width, whiteViewHeight)];
        self.whiteView.backgroundColor = [UIColor whiteColor];
        [self addSubview:self.whiteView];
        
        //完成
        UIButton *bConfirm = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, width, 40)];
        [bConfirm setTitle:@"完成" forState:0];
        [bConfirm setTitleColor:[UIColor cyanColor] forState:0];
        [bConfirm addTarget:self action:@selector(buttonConfirm) forControlEvents:UIControlEventTouchUpInside];
        [self.whiteView addSubview:bConfirm];
        
        CGFloat edge = 20.f;
        CGFloat labelWidth = (width - edge * 5) / 2;
        
        //开始时间
        _bStart = [[UIButton alloc]initWithFrame:CGRectMake(20, CGRectGetMaxY(bConfirm.frame) + edge * 2, labelWidth, 40)];
        [_bStart setTitle:[self dateFormatWithDate:[NSDate date]] forState:0];
        [_bStart setTitleColor:[UIColor cyanColor] forState:0];
        _bStart.tag = 1000;
        [_bStart addTarget:self action:@selector(buttonTypeTimeSelect:) forControlEvents:UIControlEventTouchUpInside];
        [self.whiteView addSubview:_bStart];
        UIImageView *ivLineStart = [[UIImageView alloc]initWithFrame:CGRectMake(CGRectGetMinX(_bStart.frame), CGRectGetMaxY(_bStart.frame), CGRectGetWidth(_bStart.frame), 1)];
        ivLineStart.backgroundColor = [UIColor lightGrayColor];
        [self.whiteView addSubview:ivLineStart];
        
        //至
        UILabel *lFromTo = [[UILabel alloc]initWithFrame:CGRectMake(CGRectGetMaxX(_bStart.frame) + edge, CGRectGetMinY(_bStart.frame), edge, CGRectGetHeight(_bStart.frame))];
        lFromTo.text = @"至";
        lFromTo.textColor = [UIColor blackColor];
        lFromTo.textAlignment = NSTextAlignmentCenter;
        lFromTo.font = [UIFont systemFontOfSize:16];
        [self.whiteView addSubview:lFromTo];
        
        //结束时间
        _bEnd = [[UIButton alloc]initWithFrame:CGRectMake(CGRectGetMaxX(lFromTo.frame) + edge, CGRectGetMinY(_bStart.frame), CGRectGetWidth(_bStart.frame), CGRectGetHeight(_bStart.frame))];
        [_bEnd setTitle:[self dateFormatWithDate:[NSDate date]] forState:0];
        [_bEnd setTitleColor:[UIColor lightGrayColor] forState:0];
        _bEnd.tag = 1001;
        [_bEnd addTarget:self action:@selector(buttonTypeTimeSelect:) forControlEvents:UIControlEventTouchUpInside];
        [self.whiteView addSubview:_bEnd];
        UIImageView *ivLineEnd = [[UIImageView alloc]initWithFrame:CGRectMake(CGRectGetMinX(_bEnd.frame), CGRectGetMaxY(_bEnd.frame), CGRectGetWidth(ivLineStart.frame), CGRectGetHeight(ivLineStart.frame))];
        ivLineEnd.backgroundColor = [UIColor lightGrayColor];
        [self.whiteView addSubview:ivLineEnd];
        
        //选择器
        self.selectorPicker = [[LYDateIntervalSelectorPicker alloc]initWithDatePickerView];
        self.selectorPicker.frame = CGRectMake(0, whiteViewHeight - pickerHeight, width, pickerHeight);
        self.selectorPicker.pvDelegate = self;
        [self.whiteView addSubview:self.selectorPicker];
        
        
    }
    
    -(void)buttonTypeTimeSelect:(UIButton *)sender{
        
        if (sender.tag - 1000 == 0) {
            [_bStart setTitleColor:[UIColor cyanColor] forState:0];
            [_bEnd setTitleColor:[UIColor lightGrayColor] forState:0];
            self.timeType = NO;
        }else{
            [_bStart setTitleColor:[UIColor lightGrayColor] forState:0];
            [_bEnd setTitleColor:[UIColor cyanColor] forState:0];
            self.timeType = YES;
        }
        
    }
    
    -(void)dateWithSelect:(NSDate *)date{
        
        //时间转时间戳
        NSString *time = [self dateFormatWithDate:date];
        
        //选择结束时间
        if (self.timeType) {
            self.endDate = date;
            [_bEnd setTitle:time forState:0];
        }
        
        //选择开始时间
        else{
            self.startDate = date;
            [_bStart setTitle:time forState:0];
        }
        
    }
    
    -(void)buttonConfirm{
        
        //开始时间的时间戳
        NSInteger sDate = [self timestampWithDate:self.startDate];
        //结束时间的时间戳
        NSInteger eDate = [self timestampWithDate:self.endDate];
        
        //开始时间的时间戳大于结束时间的时间戳是不对的,直接return,提示时间不对
        if (sDate > eDate) {
            NSLog(@"时间不对");
            return;
        }
        
        if (_dateBlock) {
            _dateBlock(self.startDate,self.endDate);
        }
        
    }
    
    //显示手势
    -(void)show{
        
        [[UIApplication sharedApplication].keyWindow addSubview:self];
            self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0];
        [UIView animateWithDuration:0.25 animations:^{
            self.whiteView.frame = CGRectMake(0, self->height - whiteViewHeight, self->width, whiteViewHeight);
            self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
        }];
        
    }
    
    //取消手势
    -(void)tapCancelAction{
        
        [UIView animateWithDuration:0.2 animations:^{
            self.whiteView.frame = CGRectMake(0, self->height, self->width, whiteViewHeight);
            self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0];
        } completion:^(BOOL finished) {
            [self removeFromSuperview];
        }];
        
    }
    
    //时间格式
    -(NSString *)dateFormatWithDate:(NSDate *)date{
        
        NSString *formatStr = @"yyyy-MM-dd";
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:formatStr];
        return [dateFormatter stringFromDate:date];
        
    }
    
    //时间转时间戳
    -(NSInteger)timestampWithDate:(NSDate *)date{
        return [date timeIntervalSince1970] / 1000;
    }
    
    @end
    

    3、创建一个Controller

    .h文件

    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface DateSelectorController : UIViewController
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    .m文件 —— 引入头文件
    #import "LYDateIntervalSelectorView.h"

    #import "DateSelectorController.h"
    #import "LYDateIntervalSelectorView.h"
    
    @interface DateSelectorController ()
    
    @end
    
    @implementation DateSelectorController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.view.backgroundColor = [UIColor whiteColor];
        
        [[LYDateIntervalSelectorView initClient] datePickerCompleteBlock:^(NSDate * _Nonnull startDate, NSDate * _Nonnull endDate) {
            
            NSString *formatStr = @"yyyy年MM月dd日";
            NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
            [dateFormatter setDateFormat:formatStr];
            NSLog(@"ss  %@",[dateFormatter stringFromDate:startDate]);
            NSLog(@"ee  %@",[dateFormatter stringFromDate:endDate]);
            
        }];
        
    }
    
    @end
    

    4、效果图

    效果图.gif

    5、全剧终

    我也是服了有些人了,Demo

    相关文章

      网友评论

          本文标题:iOS 年月日时间区间选择器

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