// // YUDatePicker.h // YUDatePicker // // Created by yuzhx on 15/4/26. // Copyright (c) 2015年 BruceYu. All rights reserved. // #import <UIKit/UIKit.h> #import "NSDate+YU.h" #import "YUDateConfig.h" typedef NS_ENUM(NSInteger, YUUIDatePickerMode) { UIYUDatePickerModeTime, // Displays hour, minute, and optionally AM/PM designation depending on the locale setting (e.g. 6 | 53 | PM) UIYUDatePickerModeDate, // Displays month, day, and year depending on the locale setting (e.g. November | 15 | 2007) UIYUDatePickerModeDateAndTime, // Displays date, hour, minute, and optionally AM/PM designation depending on the locale setting (e.g. Wed Nov 15 | 6 | 53 | PM) UIYUDatePickerModeCountDownTimer, // Displays hour and minute (e.g. 1 | 53) UIYUDatePickerModeDateYYYYMMDDHHmm, // (e.g. 2015年 | 05月 | 01日 | 11时 | 59分) }; NS_CLASS_AVAILABLE_IOS(6_0)@interface YUDatePicker : UIControl @property (nonatomic) YUUIDatePickerMode datePickerMode; // default is UIXYDatePickerModeDateAndTime @property (nonatomic, retain) NSLocale *locale; // default is [NSLocale currentLocale]. setting nil returns to default @property (nonatomic, copy) NSCalendar *calendar; // default is [NSCalendar currentCalendar]. setting nil returns to default @property (nonatomic, retain) NSTimeZone *timeZone; // default is nil. use current time zone or time zone from calendar @property (nonatomic, retain) NSDate *date; // default is current date when picker created. Ignored in countdown timer mode. for that mode, picker starts at 0:00 @property (nonatomic, readonly) NSString *dateStr;//return current date Formatter yyyy-MM-dd HH:mm:ss @property (nonatomic, retain) NSDate *minimumDate; // specify min/max date range. default is nil. When min > max, the values are ignored. Ignored in countdown timer mode @property (nonatomic, retain) NSDate *maximumDate; // default is nil @property (nonatomic) NSTimeInterval countDownDuration; // for UIDatePickerModeCountDownTimer, ignored otherwise. default is 0.0. limit is 23:59 (86,399 seconds). value being set is div 60 (drops remaining seconds). @property (nonatomic) NSInteger minuteInterval; // display minutes wheel with interval. interval must be evenly divided into 60. default is 1. min is 1, max is 30 - (void)setDate:(NSDate *)date animated:(BOOL)animated; // if animated is YES, animate the wheels of time to display the new date @property (nonatomic, assign) BOOL showToolbar; @end typedef void (^dateBlock)(YUDatePicker *date); @interface YUDatePicker(YU) -(void)showInView:(UIView *)view block:(dateBlock)dateBlock; -(void)hidden; @end
// // YUDatePicker.m // YUDatePicker // // Created by yuzhx on 15/4/26. // Copyright (c) 2015年 BruceYu. All rights reserved. // #import "YUDatePicker.h" #define XYNUMBEROFROWS 16384 #define XYROSE_NUMBER 99 #define PICKERHIGHR 216 #define TOOLBARHIGHT 44 @interface YUDatePicker()<UIPickerViewDelegate,UIPickerViewDataSource> { UIPickerView *PickerView; } @property (nonatomic) NSInteger yearIndex; @property (nonatomic) NSInteger monthIndex; @property (nonatomic) NSInteger dayIndex; @property (nonatomic) NSInteger hourIndex; @property (nonatomic) NSInteger minuteIndex; @property (nonatomic) NSInteger secondIndex; @property (nonatomic , strong) NSArray *amPmArray; @property (nonatomic , strong) NSMutableArray *yearArray; @property (nonatomic , strong) NSMutableArray *monthArray; @property (nonatomic , strong) NSMutableArray *dayArray; @property (nonatomic , strong) NSMutableArray *hourArray; @property (nonatomic , strong) NSMutableArray *minuteArray; @property(nonatomic,strong)NSDate *currentDate; @property (strong, nonatomic)UIToolbar *actionToolbar; @end @implementation YUDatePicker - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor whiteColor]; if (self.frame.size.height<216 || self.frame.size.width<320) { self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, PICKERHIGHR); } } return self; } - (instancetype)init { self = [super init]; if (self) { self.frame = CGRectMake(0, 0, 0, PICKERHIGHR); } return self; } -(NSDate *)date { NSString *ds = [NSString stringWithFormat:XY_FORMATSTR, self.yearArray[self.yearIndex], self.monthArray[self.monthIndex], self.dayArray[self.dayIndex], self.hourArray[self.hourIndex], self.minuteArray[self.minuteIndex] ]; NSDate *date = [NSDate dateFromString:ds withFormat:XY_FORMAT]; return date; } -(NSString *)dateStr{ NSString *ds = [NSString stringWithFormat:XY_DATESTR, self.yearArray[self.yearIndex], self.monthArray[self.monthIndex], self.dayArray[self.dayIndex], self.hourArray[self.hourIndex], self.minuteArray[self.minuteIndex] ]; return ds; } -(NSInteger)febNumber{ NSInteger day = [NSDate daysfromYear:[self.yearArray[self.yearIndex] integerValue] andMonth:[self.monthArray[self.monthIndex] integerValue]]; return day; } -(void)setMinimumDate:(NSDate *)minimumDate { if (!minimumDate) { _minimumDate = [NSDate dateWithYea:XYPICKER_MINDATE]; }else{ _minimumDate = minimumDate; } } -(void)setMaximumDate:(NSDate *)maximumDate { if (!_maximumDate) { _maximumDate = [NSDate dateWithYea:XYPICKER_MAXDATE]; }else{ _maximumDate = maximumDate; } } -(NSArray*)setDays:(NSInteger)num{ if ([_dayArray count]) { [_dayArray removeAllObjects]; } for (int i = 1; i <= num; i++) { [_dayArray addObject:[NSString stringWithFormat:@"%02d",i]]; } return _dayArray; } -(void)setCurrentDate:(NSDate *)currentDate{ if (currentDate) { _currentDate = currentDate; NSDateComponents *d = [NSDate dateComponentsFromDate:_currentDate]; self.yearIndex = d.year-XYPICKER_MINDATE; self.monthIndex = d.month -1; self.dayIndex = d.day -1; self.hourIndex = d.hour; self.minuteIndex = d.minute; self.secondIndex = d.second; } } #pragma mark - 初始化赋值操作 -(void)initData{ self.yearArray = [NSMutableArray array]; self.monthArray = [NSMutableArray array]; self.dayArray = [NSMutableArray array]; self.hourArray = [NSMutableArray array]; self.minuteArray = [NSMutableArray array]; self.amPmArray = @[@"AM",@"PM"]; for (int i=0; i<XYPICKER_MINUTE; i++) { NSString *num = [NSString stringWithFormat:@"%02d",i]; if (0<i && i<=XYPICKER_MONTH) [self.monthArray addObject:num]; if (0<i && i<=XYPICKER_DAY) [self.dayArray addObject:num]; if (i<XYPICKER_HOUR) [self.hourArray addObject:num]; [self.minuteArray addObject:num]; } for (int i=XYPICKER_MINDATE; i<XYPICKER_MAXDATE; i++) { NSString *num = [NSString stringWithFormat:@"%d",i]; [self.yearArray addObject:num]; } self.currentDate = _date; } -(void)initUI{ if (self.datePickerMode >= UIYUDatePickerModeDateYYYYMMDDHHmm ) { if (!PickerView) { PickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(0, TOOLBARHIGHT-22, self.frame.size.width, PICKERHIGHR)]; PickerView.showsSelectionIndicator = YES; // PickerView.autoresizingMask = UIViewAutoresizingFlexibleHeight; PickerView.backgroundColor = [UIColor clearColor]; PickerView.delegate = self; PickerView.dataSource = self; [self addSubview:PickerView]; } [self revertRow:_date animated:NO]; }else{ UIDatePicker *datePicker = [ [ UIDatePicker alloc] initWithFrame:CGRectMake(0,TOOLBARHIGHT-22,self.frame.size.width,PICKERHIGHR-TOOLBARHIGHT)]; datePicker.datePickerMode = (UIDatePickerMode)self.datePickerMode; datePicker.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin; [datePicker setLocale:self.locale?self.locale:[[NSLocale alloc]initWithLocaleIdentifier:@"zh_CN"]]; datePicker.calendar = self.calendar; datePicker.timeZone = self.timeZone; datePicker.date = _date; datePicker.minimumDate = self.minimumDate; datePicker.maximumDate = self.maximumDate; datePicker.minuteInterval = self.minuteInterval; datePicker.countDownDuration = self.countDownDuration; [self addSubview:datePicker]; } if (self.showToolbar) { _actionToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, TOOLBARHIGHT)]; _actionToolbar.barStyle = UIBarStyleDefault; [_actionToolbar sizeToFit]; _actionToolbar.layer.borderWidth = 0.35f; _actionToolbar.layer.borderColor = [[UIColor colorWithWhite:.8 alpha:1.0] CGColor]; UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(actionCancel:)]; UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil]; UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(actionDone:)]; [_actionToolbar setItems:[NSArray arrayWithObjects:cancelButton,flexSpace,doneBtn, nil] animated:YES]; [self addSubview:_actionToolbar]; } } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code [self initData]; [self initUI]; } #pragma mark - UIPickerViewDataSource - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { if (self.datePickerMode == UIYUDatePickerModeDateYYYYMMDDHHmm){ return 5; } return 0; } - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { return XYNUMBEROFROWS; } #pragma mark - UIPickerViewDelegate - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component { switch (self.datePickerMode) { case UIYUDatePickerModeDateYYYYMMDDHHmm:{ if (component == 0) { return 75; } return 55; } break; default: break; } return 50; } - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{ return 32; } - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { NSInteger count = 0; switch (self.datePickerMode) { case UIYUDatePickerModeDateYYYYMMDDHHmm:{ if (component == 0) { self.yearIndex = row%(count=self.yearArray.count); } if (component == 1) { self.monthIndex = row%(count=self.monthArray.count); [self setDays:self.febNumber]; [pickerView selectRow:self.dayIndex + self.dayArray.count * XYROSE_NUMBER inComponent:2 animated:NO]; } if (component == 2) { self.dayIndex = row%(count=self.dayArray.count); } if (component == 3) { self.hourIndex = row%(count=self.hourArray.count); } if (component == 4) { self.minuteIndex = row%(count=self.minuteArray.count); } } break; default: break; } [self selectDid:component]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self revertRow:self.date animated:NO]; }); } - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { UILabel *l = (UILabel *)view; if (!l) { l = [[UILabel alloc] init]; l.textAlignment = NSTextAlignmentCenter; } l.backgroundColor = [UIColor clearColor]; [l setFont:[UIFont systemFontOfSize:23]]; UIColor *textColor = [UIColor blackColor]; NSString *title; switch (self.datePickerMode) { case UIYUDatePickerModeDateYYYYMMDDHHmm:{ if (component==0) { title = [NSString stringWithFormat:@"%@年",self.yearArray[row%self.yearArray.count]]; textColor = [self yearColorRow:row]; } if (component==1) { title = [NSString stringWithFormat:@"%@月",self.monthArray[row%self.monthArray.count]]; textColor = [self monthColorRow:row]; } if (component==2) { title = [NSString stringWithFormat:@"%@日",self.dayArray[row%self.dayArray.count]]; textColor = [self dayColorRow:row]; } if (component==3) { title = [NSString stringWithFormat:@"%@时",self.hourArray[row%self.hourArray.count]]; textColor = [self hourColorRow:row]; } if (component==4) { title = [NSString stringWithFormat:@"%@分",self.minuteArray[row%self.minuteArray.count]]; textColor = [self minuteColorRow:row]; } } break; default: break; } l.text = title; l.textColor = textColor; return l; } #pragma mark - #pragma mark - Private - (void)selectDid:(NSInteger)component { if ([self exceedMin:self.date]) { [self revertRow:self.minimumDate animated:YES]; }else if ([self exceedMax:self.date]){ [self revertRow:self.maximumDate animated:YES]; } [self sendActionsForControlEvents:UIControlEventValueChanged]; } -(void)revertRow:(NSDate*)date animated:(BOOL)animated{ NSArray *arry = [self getNowDateArry:date]; NSInteger row = 1; for (int i=0; i<arry.count; i++) { if (i%2) { [PickerView selectRow:[arry[i]integerValue]+row inComponent:i/2 animated:animated]; }else{ row = [arry[i]integerValue]*XYROSE_NUMBER; } } } - (NSArray *)getNowDateArry:(NSDate*)date { NSArray *iArr = nil; self.currentDate = date; if (self.datePickerMode == UIYUDatePickerModeDateYYYYMMDDHHmm){ iArr = @[I2S(self.yearArray.count),I2S(self.yearIndex), I2S(self.monthArray.count),I2S(self.monthIndex), I2S(self.dayArray.count),I2S(self.dayIndex), I2S(self.hourArray.count),I2S(self.hourIndex), I2S(self.minuteArray.count),I2S(self.minuteIndex)]; } iArr ? 0 :(iArr=[NSArray array]); return iArr; } -(UIColor*)rowColor:(NSDate*)date{ if ([self exceedDate:date]) { return XY_LIGHTGRAY; } return XY_BLACK; } -(UIColor*)yearColorRow:(NSInteger)row{ NSString *ds = [NSString stringWithFormat:XY_DATESTR, self.yearArray[row% self.yearArray.count], self.monthArray[self.monthIndex], self.dayArray[self.dayIndex], self.hourArray[self.hourIndex], self.minuteArray[self.minuteIndex] ]; NSDate *date = [NSDate dateFromString:ds withFormat:XY_FORMAT]; return [self rowColor:date]; } -(UIColor*)monthColorRow:(NSInteger)row{ NSString *ds = [NSString stringWithFormat:XY_DATESTR, self.yearArray[self.yearIndex], self.monthArray[row%self.monthArray.count], self.dayArray[self.dayIndex], self.hourArray[self.hourIndex], self.minuteArray[self.minuteIndex] ]; NSDate *date = [NSDate dateFromString:ds withFormat:XY_FORMAT]; return [self rowColor:date]; } -(UIColor*)dayColorRow:(NSInteger)row{ NSString *ds = [NSString stringWithFormat:XY_DATESTR, self.yearArray[self.yearIndex], self.monthArray[self.monthIndex], self.dayArray[row%self.dayArray.count], self.hourArray[self.hourIndex], self.minuteArray[self.minuteIndex] ]; NSDate *date = [NSDate dateFromString:ds withFormat:XY_FORMAT]; return [self rowColor:date]; } -(UIColor*)hourColorRow:(NSInteger)row{ NSString *ds = [NSString stringWithFormat:XY_DATESTR, self.yearArray[self.yearIndex], self.monthArray[self.monthIndex], self.dayArray[self.dayIndex], self.hourArray[row%self.hourArray.count], self.minuteArray[self.minuteIndex] ]; NSDate *date = [NSDate dateFromString:ds withFormat:XY_FORMAT]; return [self rowColor:date]; } -(UIColor*)minuteColorRow:(NSInteger)row{ NSString *ds = [NSString stringWithFormat:XY_DATESTR, self.yearArray[self.yearIndex], self.monthArray[self.monthIndex], self.dayArray[self.dayIndex], self.hourArray[self.hourIndex], self.minuteArray[row%self.minuteArray.count] ]; NSDate *date = [NSDate dateFromString:ds withFormat:XY_FORMAT]; return [self rowColor:date]; } -(BOOL)exceedMin:(NSDate*)date{ if ([date compare:self.minimumDate] == NSOrderedAscending) { return YES; } return NO; } -(BOOL)exceedMax:(NSDate*)date{ if ([date compare:self.maximumDate] == NSOrderedDescending){ return YES; } return NO; } -(BOOL)exceedDate:(NSDate*)date{ BOOL exD = NO; if ([self exceedMin:date]) { exD = YES; }else if ([self exceedMax:date]){ exD = YES; } return exD; } - (void)setDate:(NSDate *)date animated:(BOOL)animated{ self.currentDate = date; [self revertRow:date animated:YES]; } - (void)actionCancel:(id)sender { [self hidden]; } - (void)actionDone:(id)sender { [self hidden]; } @end @implementation YUDatePicker(YU) -(void)showInView:(UIView *)view block:(dateBlock)dateBlock{ if (self.superview) { [self removeFromSuperview]; } [self setFrame:CGRectMake(0, view.frame.size.height + PICKERHIGHR, view.frame.size.width, PICKERHIGHR)]; [UIView animateWithDuration:0.35 animations:^{ [self setFrame:CGRectMake( CGRectGetMinX(self.frame), CGRectGetHeight(view.frame)-PICKERHIGHR, view.frame.size.width, PICKERHIGHR)]; }]; [view addSubview:self]; if (dateBlock) { dateBlock(self); } } -(void)Dismiss { [UIView animateWithDuration:0.35 animations:^{ [self setFrame:CGRectMake(0, 800+ self.frame.size.height, self.frame.size.width, PICKERHIGHR)]; } completion:^(BOOL finished) { [self removeFromSuperview]; }]; } -(void)hidden{ if (!self.superview) { return; } [self Dismiss]; } @end
软件地址:http://www.oschina.net/p/yudatepicker