支持四种格式,可控制可选时间范围,如下:
(1)年月日时分
(2)年月日
(3)月日时分
(4)时分
效果如下:
iPhone 5s
iPhone 6
iPhone 6 Plus
ViewController.h
1 #import <UIKit/UIKit.h> 2 #import "KMDatePicker.h" 3 4 @interface ViewController : UIViewController <UITextFieldDelegate, KMDatePickerDelegate> 5 @property (strong, nonatomic) UITextField *txtFCurrent; 6 7 @property (strong, nonatomic) IBOutlet UITextField *txtFYearMonthDayHourMinute; 8 @property (strong, nonatomic) IBOutlet UITextField *txtFMonthDayHourMinute; 9 @property (strong, nonatomic) IBOutlet UITextField *txtFYearMonthDay; 10 @property (strong, nonatomic) IBOutlet UITextField *txtFHourMinute; 11 @property (strong, nonatomic) IBOutlet UITextField *txtFLimitedDate; 12 13 @end
ViewController.m
1 #import "ViewController.h" 2 #import "DateHelper.h" 3 #import "NSDate+CalculateDay.h" 4 5 @interface ViewController () 6 - (void)layoutUI; 7 @end 8 9 @implementation ViewController 10 11 - (void)viewDidLoad { 12 [super viewDidLoad]; 13 14 [self layoutUI]; 15 } 16 17 - (void)didReceiveMemoryWarning { 18 [super didReceiveMemoryWarning]; 19 // Dispose of any resources that can be recreated. 20 } 21 22 - (void)layoutUI { 23 CGRect rect = [[UIScreen mainScreen] bounds]; 24 rect = CGRectMake(0.0, 0.0, rect.size.width, 216.0); 25 //年月日时分 26 KMDatePicker *datePicker = [[KMDatePicker alloc] 27 initWithFrame:rect 28 delegate:self 29 datePickerStyle:KMDatePickerStyleYearMonthDayHourMinute]; 30 _txtFYearMonthDayHourMinute.inputView = datePicker; 31 _txtFYearMonthDayHourMinute.delegate = self; 32 33 //年月日 34 datePicker = [[KMDatePicker alloc] 35 initWithFrame:rect 36 delegate:self 37 datePickerStyle:KMDatePickerStyleYearMonthDay]; 38 _txtFYearMonthDay.inputView = datePicker; 39 _txtFYearMonthDay.delegate = self; 40 41 //月日时分 42 datePicker = [[KMDatePicker alloc] 43 initWithFrame:rect 44 delegate:self 45 datePickerStyle:KMDatePickerStyleMonthDayHourMinute]; 46 _txtFMonthDayHourMinute.inputView = datePicker; 47 _txtFMonthDayHourMinute.delegate = self; 48 49 //时分 50 datePicker = [[KMDatePicker alloc] 51 initWithFrame:rect 52 delegate:self 53 datePickerStyle:KMDatePickerStyleHourMinute]; 54 _txtFHourMinute.inputView = datePicker; 55 _txtFHourMinute.delegate = self; 56 57 //年月日时分;限制时间范围 58 datePicker = [[KMDatePicker alloc] 59 initWithFrame:rect 60 delegate:self 61 datePickerStyle:KMDatePickerStyleYearMonthDayHourMinute]; 62 datePicker.minLimitedDate = [[DateHelper localeDate] addMonthAndDay:-24 days:0]; 63 datePicker.maxLimitedDate = [datePicker.minLimitedDate addMonthAndDay:48 days:0]; 64 _txtFLimitedDate.inputView = datePicker; 65 _txtFLimitedDate.delegate = self; 66 } 67 68 - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { 69 [self.view endEditing:YES]; 70 } 71 72 #pragma mark - UITextFieldDelegate 73 - (void)textFieldDidBeginEditing:(UITextField *)textField { 74 _txtFCurrent = textField; 75 } 76 77 #pragma mark - KMDatePickerDelegate 78 - (void)datePicker:(KMDatePicker *)datePicker didSelectDate:(KMDatePickerDateModel *)datePickerDate { 79 NSString *dateStr = [NSString stringWithFormat:@"%@-%@-%@ %@:%@ %@", 80 datePickerDate.year, 81 datePickerDate.month, 82 datePickerDate.day, 83 datePickerDate.hour, 84 datePickerDate.minute, 85 datePickerDate.weekdayName 86 ]; 87 _txtFCurrent.text = dateStr; 88 } 89 90 @end
Main.storyboard
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="15A284" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r"> 3 <dependencies> 4 <deployment identifier="iOS"/> 5 <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/> 6 </dependencies> 7 <scenes> 8 <!--View Controller--> 9 <scene sceneID="tne-QT-ifu"> 10 <objects> 11 <viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController"> 12 <layoutGuides> 13 <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> 14 <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> 15 </layoutGuides> 16 <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> 17 <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> 18 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> 19 <subviews> 20 <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="YearMonthDayHourMinute" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="RU4-aD-bI3"> 21 <rect key="frame" x="180" y="58" width="240" height="30"/> 22 <animations/> 23 <constraints> 24 <constraint firstAttribute="width" constant="240" id="9Oi-OR-Ru9"/> 25 <constraint firstAttribute="height" constant="30" id="Wsa-Pd-EDg"/> 26 </constraints> 27 <fontDescription key="fontDescription" type="system" pointSize="14"/> 28 <textInputTraits key="textInputTraits"/> 29 </textField> 30 <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="MonthDayHourMinute" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="KFz-2Q-yIQ"> 31 <rect key="frame" x="180" y="170" width="240" height="30"/> 32 <animations/> 33 <constraints> 34 <constraint firstAttribute="height" constant="30" id="Qxz-uf-Ngd"/> 35 <constraint firstAttribute="width" constant="240" id="pTd-xH-c6N"/> 36 </constraints> 37 <fontDescription key="fontDescription" type="system" pointSize="14"/> 38 <textInputTraits key="textInputTraits"/> 39 </textField> 40 <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="YearMonthDay" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="V6m-6E-ZuV"> 41 <rect key="frame" x="180" y="113" width="240" height="30"/> 42 <animations/> 43 <constraints> 44 <constraint firstAttribute="height" constant="30" id="CzE-ap-TTQ"/> 45 <constraint firstAttribute="width" constant="240" id="eCi-kT-2tg"/> 46 </constraints> 47 <fontDescription key="fontDescription" type="system" pointSize="14"/> 48 <textInputTraits key="textInputTraits"/> 49 </textField> 50 <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="HourMinute" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Neu-Vj-fG0"> 51 <rect key="frame" x="180" y="228" width="240" height="30"/> 52 <animations/> 53 <constraints> 54 <constraint firstAttribute="width" constant="240" id="XBx-GA-ad2"/> 55 <constraint firstAttribute="height" constant="30" id="tON-2M-EMP"/> 56 </constraints> 57 <fontDescription key="fontDescription" type="system" pointSize="14"/> 58 <textInputTraits key="textInputTraits"/> 59 </textField> 60 <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="LimitedDate" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="vt1-Aj-i6Y"> 61 <rect key="frame" x="180" y="280" width="240" height="30"/> 62 <animations/> 63 <constraints> 64 <constraint firstAttribute="height" constant="30" id="QSC-Me-tpx"/> 65 <constraint firstAttribute="width" constant="240" id="X0a-1i-Z2T"/> 66 </constraints> 67 <fontDescription key="fontDescription" type="system" pointSize="14"/> 68 <textInputTraits key="textInputTraits"/> 69 </textField> 70 </subviews> 71 <animations/> 72 <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> 73 <constraints> 74 <constraint firstItem="Neu-Vj-fG0" firstAttribute="top" secondItem="KFz-2Q-yIQ" secondAttribute="bottom" constant="28" id="4Wp-rC-NJF"/> 75 <constraint firstItem="RU4-aD-bI3" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="38" id="EU7-1f-tVl"/> 76 <constraint firstItem="RU4-aD-bI3" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="FUG-e6-Qhi"/> 77 <constraint firstItem="Neu-Vj-fG0" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="HRH-7N-oaY"/> 78 <constraint firstItem="V6m-6E-ZuV" firstAttribute="top" secondItem="RU4-aD-bI3" secondAttribute="bottom" constant="25" id="Ind-TZ-Rzm"/> 79 <constraint firstItem="V6m-6E-ZuV" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="JTW-zd-LlI"/> 80 <constraint firstItem="KFz-2Q-yIQ" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="LpF-Jq-wwJ"/> 81 <constraint firstItem="KFz-2Q-yIQ" firstAttribute="top" secondItem="V6m-6E-ZuV" secondAttribute="bottom" constant="27" id="TyY-DA-rn2"/> 82 <constraint firstItem="vt1-Aj-i6Y" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="g0Z-bZ-p3g"/> 83 <constraint firstItem="vt1-Aj-i6Y" firstAttribute="top" secondItem="Neu-Vj-fG0" secondAttribute="bottom" constant="22" id="tyA-YZ-slJ"/> 84 </constraints> 85 </view> 86 <connections> 87 <outlet property="txtFHourMinute" destination="Neu-Vj-fG0" id="wPd-UK-nh5"/> 88 <outlet property="txtFLimitedDate" destination="vt1-Aj-i6Y" id="MzT-tx-thY"/> 89 <outlet property="txtFMonthDayHourMinute" destination="KFz-2Q-yIQ" id="Hp6-Ve-tYI"/> 90 <outlet property="txtFYearMonthDay" destination="V6m-6E-ZuV" id="0cJ-v8-xh3"/> 91 <outlet property="txtFYearMonthDayHourMinute" destination="RU4-aD-bI3" id="neo-JQ-wV5"/> 92 </connections> 93 </viewController> 94 <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> 95 </objects> 96 </scene> 97 </scenes> 98 </document>
NSDate+CalculateDay.h
1 #import <Foundation/Foundation.h> 2 3 @interface NSDate (CalculateDay) 4 /** 5 * 获取对应月份的天数 6 * 7 * @return 对应月份的天数 8 */ 9 - (NSUInteger)daysOfMonth; 10 11 /** 12 * 获取对应年份的天数 13 * 14 * @return 对应年份的天数 15 */ 16 - (NSUInteger)daysOfYear; 17 18 /** 19 * 获取对应月份的第一天时间 20 * 21 * @return 对应月份的第一天时间 22 */ 23 - (NSDate *)firstDayOfMonth; 24 25 /** 26 * 获取对应月份的最后一天时间 27 * 28 * @return 对应月份的最后一天时间 29 */ 30 - (NSDate *)lastDayOfMonth; 31 32 /** 33 * 根据月数和天数间隔,获取间隔后的时间 34 * 35 * @param months 月数间隔 36 * @param days 天数间隔 37 * 38 * @return 间隔后的时间 39 */ 40 - (NSDate *)addMonthAndDay:(NSUInteger)months days:(NSUInteger)days; 41 42 /** 43 * 根据开始时间和结束时间,获取间隔的时间数组 44 * 45 * @param toDate 结束时间 46 * 47 * @return 间隔的时间数组(月数和天数;toDate-fromDate的比较值是有符号整数NSInteger,所以存在负数的可能) 48 */ 49 - (NSArray *)monthAndDayBetweenTwoDates:(NSDate *)toDate; 50 51 /** 52 * 获取对应周期的数字 53 * 54 * @return 对应周期的数字(1:周日、2:周一、3:周二、4:周三、5:周四、6:周五、7:周六) 55 */ 56 - (NSInteger)weekday; 57 58 /** 59 * 根据地区标示符,获取对应周期的名称 60 * 61 * @param isShortName 是否是短名称 62 * @param localeIdentifier 地区标示符(中国:zh_CN、美国:en_US) 63 * 64 * @return 对应周期的名称 65 */ 66 - (NSString *)weekdayName:(BOOL)isShortName localeIdentifier:(NSString *)localeIdentifier; 67 68 /** 69 * 获取对应周期的中文名称 70 * 71 * @param isShortName 是否是短名称 72 * 73 * @return 对应周期的中文名称(短名称:周日、周一、周二、周三、周四、周五、周六)(长名称:星期日、星期一、星期二、星期三、星期四、星期五、星期六) 74 */ 75 - (NSString *)weekdayNameCN:(BOOL)isShortName; 76 77 /** 78 * 获取对应周期的英文名称 79 * 80 * @param isShortName 是否是短名称 81 * 82 * @return 对应周期的英文名称(短名称:Sun、Mon、Tue、Wed、Thu、Fri、Sat)(长名称:Sunday、Monday、Tuesday、Wednesday、Thursday、Friday、Saturday) 83 */ 84 - (NSString *)weekdayNameEN:(BOOL)isShortName; 85 @end
NSDate+CalculateDay.m
1 #import "NSDate+CalculateDay.h" 2 3 @implementation NSDate (CalculateDay) 4 5 - (NSUInteger)daysOfMonth { 6 NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 7 NSRange range = [gregorian rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:self]; 8 return range.length; 9 } 10 11 - (NSUInteger)daysOfYear { 12 NSUInteger days = 0; 13 NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 14 NSDateComponents *comps = [gregorian components:NSCalendarUnitYear fromDate:self]; 15 16 for (NSUInteger i=1; i<=12; i++) { 17 [comps setMonth:i]; 18 days += [[gregorian dateFromComponents:comps] daysOfMonth]; 19 } 20 return days; 21 } 22 23 - (NSDate *)firstDayOfMonth { 24 NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 25 unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; 26 NSDateComponents *comps = [gregorian components:unitFlags fromDate:self]; 27 [comps setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; //使用UTC或GMT解决时区相差8小时的问题 28 [comps setDay:1]; 29 30 return [gregorian dateFromComponents:comps]; 31 } 32 33 - (NSDate *)lastDayOfMonth { 34 NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 35 unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; 36 NSDateComponents *comps = [gregorian components:unitFlags fromDate:self]; 37 [comps setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; //使用UTC或GMT解决时区相差8小时的问题 38 [comps setDay:[self daysOfMonth]]; 39 40 return [gregorian dateFromComponents:comps]; 41 } 42 43 - (NSDate *)addMonthAndDay:(NSUInteger)months days:(NSUInteger)days { 44 NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 45 NSDateComponents *comps = [NSDateComponents new]; 46 [comps setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; //使用UTC或GMT解决时区相差8小时的问题 47 [comps setMonth:months]; 48 [comps setDay:days]; 49 50 return [gregorian dateByAddingComponents:comps toDate:self options:0]; 51 } 52 53 - (NSArray *)monthAndDayBetweenTwoDates:(NSDate *)toDate { 54 NSMutableArray *mArrMonthAndDay = [[NSMutableArray alloc] initWithCapacity:2]; 55 NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 56 unsigned unitFlags = NSCalendarUnitMonth | NSCalendarUnitDay; 57 NSDateComponents *comps = [gregorian components:unitFlags fromDate:self toDate:toDate options:0]; 58 59 [mArrMonthAndDay addObject:[NSString stringWithFormat:@"%ld", (long)[comps month]]]; 60 [mArrMonthAndDay addObject:[NSString stringWithFormat:@"%ld", (long)[comps day]]]; 61 return mArrMonthAndDay; 62 } 63 64 - (NSInteger)weekday { 65 return [[[NSCalendar currentCalendar] components:NSCalendarUnitWeekday fromDate:self] weekday]; 66 } 67 68 - (NSString *)weekdayName:(BOOL)isShortName localeIdentifier:(NSString *)localeIdentifier { 69 NSDateFormatter *formatter = [NSDateFormatter new]; 70 formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; 71 formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:localeIdentifier]; 72 formatter.dateFormat = isShortName ? @"EE" : @"EEEE"; 73 return [formatter stringFromDate:self]; 74 } 75 76 - (NSString *)weekdayNameCN:(BOOL)isShortName { 77 /* 78 //方法一: 79 NSArray *arrWeekdayName = 80 isShortName 81 ? @[ @"周日", 82 @"周一", 83 @"周二", 84 @"周三", 85 @"周四", 86 @"周五", 87 @"周六" ] 88 : @[ 89 @"星期日", 90 @"星期一", 91 @"星期二", 92 @"星期三", 93 @"星期四", 94 @"星期五", 95 @"星期六" 96 ]; 97 98 NSInteger weekday = [self weekday]; 99 return arrWeekdayName[weekday - 1]; 100 */ 101 102 //方法二: 103 return [self weekdayName:isShortName localeIdentifier:@"zh_CN"]; 104 } 105 106 - (NSString *)weekdayNameEN:(BOOL)isShortName { 107 return [self weekdayName:isShortName localeIdentifier:@"en_US"]; 108 } 109 110 @end
DateHelper.h
1 #import <Foundation/Foundation.h> 2 3 @interface DateHelper : NSObject 4 /** 5 * 获取本地当前时间 6 * 7 * @return 本地当前时间 8 */ 9 + (NSDate *)localeDate; 10 11 /** 12 * 根据时间字符串和其格式,获取对应的时间 13 * 14 * @param dateStr 时间字符串 15 * @param format 时间字符串格式(默认值为@"yyyy-MM-dd HH:mm") 16 * 17 * @return 对应的时间 18 */ 19 + (NSDate *)dateFromString:(NSString *)dateStr withFormat:(NSString *)format; 20 21 /** 22 * 根据时间和其格式,获取对应的时间字符串 23 * 24 * @param date 时间 25 * @param format 时间字符串格式(默认值为@"yyyy-MM-dd HH:mm") 26 * 27 * @return 对应的时间字符串 28 */ 29 + (NSString *)dateToString:(NSDate *)date withFormat:(NSString *)format; 30 31 @end
DateHelper.m
1 #import "DateHelper.h" 2 3 @implementation DateHelper 4 5 + (NSDate *)localeDate { 6 NSDate *date = [NSDate date]; 7 NSTimeZone *zone = [NSTimeZone systemTimeZone]; 8 NSInteger interval = [zone secondsFromGMTForDate:date]; 9 return [date dateByAddingTimeInterval:interval]; 10 } 11 12 + (NSDate *)dateFromString:(NSString *)dateStr withFormat:(NSString *)format { 13 NSDateFormatter *formatter = [NSDateFormatter new]; 14 formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; 15 formatter.dateFormat = format ?: @"yyyy-MM-dd HH:mm"; 16 return [formatter dateFromString:dateStr]; 17 } 18 19 + (NSString *)dateToString:(NSDate *)date withFormat:(NSString *)format { 20 NSDateFormatter *formatter = [NSDateFormatter new]; 21 formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; 22 formatter.dateFormat = format ?: @"yyyy-MM-dd HH:mm"; 23 return [formatter stringFromDate:date]; 24 } 25 26 @end
KMDatePickerDateModel.h
1 #import <Foundation/Foundation.h> 2 3 @interface KMDatePickerDateModel : NSObject 4 @property (copy, nonatomic) NSString *year; 5 @property (copy, nonatomic) NSString *month; 6 @property (copy, nonatomic) NSString *day; 7 @property (copy, nonatomic) NSString *hour; 8 @property (copy, nonatomic) NSString *minute; 9 @property (copy, nonatomic) NSString *weekdayName; 10 11 - (instancetype)initWithDate:(NSDate *)date; 12 13 @end
KMDatePickerDateModel.m
1 #import "KMDatePickerDateModel.h" 2 #import "NSDate+CalculateDay.h" 3 4 @implementation KMDatePickerDateModel 5 6 - (instancetype)initWithDate:(NSDate *)date { 7 if (self = [super init]) { 8 NSDateFormatter *formatter = [NSDateFormatter new]; 9 formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; 10 formatter.dateFormat = @"yyyyMMddHHmm"; 11 NSString *dateStr = [formatter stringFromDate:date]; 12 13 _year = [dateStr substringWithRange:NSMakeRange(0, 4)]; 14 _month = [dateStr substringWithRange:NSMakeRange(4, 2)]; 15 _day = [dateStr substringWithRange:NSMakeRange(6, 2)]; 16 _hour = [dateStr substringWithRange:NSMakeRange(8, 2)]; 17 _minute = [dateStr substringWithRange:NSMakeRange(10, 2)]; 18 _weekdayName = [date weekdayNameCN:YES]; 19 } 20 return self; 21 } 22 23 @end
KMDatePicker.h
1 #import <UIKit/UIKit.h> 2 #import "KMDatePickerDateModel.h" 3 4 typedef NS_ENUM(NSUInteger, KMDatePickerStyle) { 5 KMDatePickerStyleYearMonthDayHourMinute, 6 KMDatePickerStyleYearMonthDay, 7 KMDatePickerStyleMonthDayHourMinute, 8 KMDatePickerStyleHourMinute 9 }; 10 11 @protocol KMDatePickerDelegate; 12 @interface KMDatePicker : UIView <UIPickerViewDataSource, UIPickerViewDelegate> 13 @property (weak, nonatomic) id<KMDatePickerDelegate> delegate; 14 @property (assign, nonatomic) KMDatePickerStyle datePickerStyle; 15 @property (strong, nonatomic) NSDate *minLimitedDate; //最小限制时间;默认值为1970-01-01 00:00 16 @property (strong, nonatomic) NSDate *maxLimitedDate; //最大限制时间;默认值为2060-12-31 23:59 17 @property (strong, nonatomic) NSDate *scrollToDate; //滚动到指定时间;默认值为当前时间 18 19 - (instancetype)initWithFrame:(CGRect)frame delegate:(id<KMDatePickerDelegate>)delegate datePickerStyle:(KMDatePickerStyle)datePickerStyle; 20 21 @end 22 23 @protocol KMDatePickerDelegate <NSObject> 24 @required 25 - (void)datePicker:(KMDatePicker *)datePicker didSelectDate:(KMDatePickerDateModel *)datePickerDate; 26 27 @end
KMDatePicker.m
1 #import "KMDatePicker.h" 2 #import "NSDate+CalculateDay.h" 3 #import "DateHelper.h" 4 5 #define kDefaultMinLimitedDate @"1970-01-01 00:00" 6 #define kDefaultMaxLimitedDate @"2060-12-31 23:59" 7 #define kMonthCountOfEveryYear 12 8 #define kHourCountOfEveryDay 24 9 #define kMinuteCountOfEveryHour 60 10 #define kRowDisabledStatusColor [UIColor redColor] 11 #define kRowNormalStatusColor [UIColor blackColor] 12 #define kWidthOfTotal self.frame.size.width 13 #define kHeightOfButtonContentView 35.0 14 #define kButtonNormalStatusColor [UIColor colorWithRed:0.0 green:0.5 blue:1.0 alpha:1.0] 15 16 @interface KMDatePicker () { 17 UIPickerView *pikV; 18 19 //最小和最大限制时间、滚动到指定时间实体对象实例 20 KMDatePickerDateModel *datePickerDateMinLimited; 21 KMDatePickerDateModel *datePickerDateMaxLimited; 22 KMDatePickerDateModel *datePickerDateScrollTo; 23 24 //存储时间数据源的数组 25 NSMutableArray *mArrYear; 26 NSMutableArray *mArrMonth; 27 NSMutableArray *mArrDay; 28 NSMutableArray *mArrHour; 29 NSMutableArray *mArrMinute; 30 31 //时间数据源的数组中,选中元素的索引 32 NSInteger yearIndex; 33 NSInteger monthIndex; 34 NSInteger dayIndex; 35 NSInteger hourIndex; 36 NSInteger minuteIndex; 37 } 38 39 - (void)addUnitLabel:(NSString *)text withPointX:(CGFloat)pointX; 40 - (NSUInteger)daysOfMonth; 41 - (void)reloadDayArray; 42 - (void)loadData; 43 - (void)scrollToDateIndexPosition; 44 - (void)playDelegateAfterSelectedRow; 45 - (BOOL)validatedDate:(NSDate *)date; 46 - (BOOL)canShowScrollToNowButton; 47 - (void)cancel:(UIButton *)sender; 48 - (void)scrollToNowDateIndexPosition:(UIButton *)sender; 49 - (void)confirm:(UIButton *)sender; 50 - (UIColor *)monthRowTextColor:(NSInteger)row; 51 - (UIColor *)dayRowTextColor:(NSInteger)row; 52 - (UIColor *)hourRowTextColor:(NSInteger)row; 53 - (UIColor *)minuteRowTextColor:(NSInteger)row; 54 55 @end 56 57 @implementation KMDatePicker 58 59 - (instancetype)init { 60 if (self = [super init]) { 61 self.backgroundColor = [UIColor whiteColor]; 62 } 63 return self; 64 } 65 66 - (instancetype)initWithFrame:(CGRect)frame { 67 if (self = [super initWithFrame:frame]) { 68 self.backgroundColor = [UIColor whiteColor]; 69 } 70 return self; 71 } 72 73 - (instancetype)initWithFrame:(CGRect)frame delegate:(id<KMDatePickerDelegate>)delegate datePickerStyle:(KMDatePickerStyle)datePickerStyle { 74 _delegate = delegate; 75 _datePickerStyle = datePickerStyle; 76 return [self initWithFrame:frame]; 77 } 78 79 #pragma mark - 自定义方法 80 - (void)addUnitLabel:(NSString *)text withPointX:(CGFloat)pointX { 81 CGFloat pointY = pikV.frame.size.height/2 - 10.0 + kHeightOfButtonContentView; 82 UILabel *lblUnit = [[UILabel alloc] initWithFrame:CGRectMake(pointX, pointY, 20.0, 20.0)]; 83 lblUnit.text = text; 84 lblUnit.textAlignment = NSTextAlignmentCenter; 85 lblUnit.textColor = [UIColor blackColor]; 86 lblUnit.backgroundColor = [UIColor clearColor]; 87 lblUnit.font = [UIFont systemFontOfSize:18.0]; 88 lblUnit.layer.shadowColor = [[UIColor whiteColor] CGColor]; 89 lblUnit.layer.shadowOpacity = 0.5; 90 lblUnit.layer.shadowRadius = 5.0; 91 [self addSubview:lblUnit]; 92 } 93 94 - (NSUInteger)daysOfMonth { 95 NSString *dateStr = [NSString stringWithFormat:@"%@-%@-01 00:00", mArrYear[yearIndex], mArrMonth[monthIndex]]; 96 return [[DateHelper dateFromString:dateStr withFormat:@"yyyy-MM-dd HH:mm"] daysOfMonth]; 97 } 98 99 - (void)reloadDayArray { 100 mArrDay = [NSMutableArray new]; 101 for (NSUInteger i=1, len=[self daysOfMonth]; i<=len; i++) { 102 [mArrDay addObject:[NSString stringWithFormat:@"%02ld", (long)i]]; 103 } 104 } 105 106 - (void)loadData { 107 //初始化最小和最大限制时间、滚动到指定时间实体对象实例 108 if (!_minLimitedDate) { 109 _minLimitedDate = [DateHelper dateFromString:kDefaultMinLimitedDate withFormat:nil]; 110 } 111 datePickerDateMinLimited = [[KMDatePickerDateModel alloc] initWithDate:_minLimitedDate]; 112 113 if (!_maxLimitedDate) { 114 _maxLimitedDate = [DateHelper dateFromString:kDefaultMaxLimitedDate withFormat:nil]; 115 } 116 datePickerDateMaxLimited = [[KMDatePickerDateModel alloc] initWithDate:_maxLimitedDate]; 117 118 //滚动到指定时间;默认值为当前时间。如果是使用自定义时间小于最小限制时间,这时就以最小限制时间为准;如果是使用自定义时间大于最大限制时间,这时就以最大限制时间为准 119 if (!_scrollToDate) { 120 _scrollToDate = [DateHelper localeDate]; 121 } 122 if ([_scrollToDate compare:_minLimitedDate] == NSOrderedAscending) { 123 _scrollToDate = _minLimitedDate; 124 } else if ([_scrollToDate compare:_maxLimitedDate] == NSOrderedDescending) { 125 _scrollToDate = _maxLimitedDate; 126 } 127 datePickerDateScrollTo = [[KMDatePickerDateModel alloc] initWithDate:_scrollToDate]; 128 129 //初始化存储时间数据源的数组 130 //年 131 mArrYear = [NSMutableArray new]; 132 for (NSInteger beginVal=[datePickerDateMinLimited.year integerValue], endVal=[datePickerDateMaxLimited.year integerValue]; beginVal<=endVal; beginVal++) { 133 [mArrYear addObject:[NSString stringWithFormat:@"%ld", (long)beginVal]]; 134 } 135 yearIndex = [datePickerDateScrollTo.year integerValue] - [datePickerDateMinLimited.year integerValue]; 136 137 //月 138 mArrMonth = [[NSMutableArray alloc] initWithCapacity:kMonthCountOfEveryYear]; 139 for (NSInteger i=1; i<=kMonthCountOfEveryYear; i++) { 140 [mArrMonth addObject:[NSString stringWithFormat:@"%02ld", (long)i]]; 141 } 142 monthIndex = [datePickerDateScrollTo.month integerValue] - 1; 143 144 //日 145 [self reloadDayArray]; 146 dayIndex = [datePickerDateScrollTo.day integerValue] - 1; 147 148 //时 149 mArrHour = [[NSMutableArray alloc] initWithCapacity:kHourCountOfEveryDay]; 150 for (NSInteger i=0; i<kHourCountOfEveryDay; i++) { 151 [mArrHour addObject:[NSString stringWithFormat:@"%02ld", (long)i]]; 152 } 153 hourIndex = [datePickerDateScrollTo.hour integerValue]; 154 155 //分 156 mArrMinute = [[NSMutableArray alloc] initWithCapacity:kMinuteCountOfEveryHour]; 157 for (NSInteger i=0; i<kMinuteCountOfEveryHour; i++) { 158 [mArrMinute addObject:[NSString stringWithFormat:@"%02ld", (long)i]]; 159 } 160 minuteIndex = [datePickerDateScrollTo.minute integerValue]; 161 } 162 163 - (void)scrollToDateIndexPosition { 164 NSArray *arrIndex; 165 switch (_datePickerStyle) { 166 case KMDatePickerStyleYearMonthDayHourMinute: { 167 arrIndex = @[ 168 [NSNumber numberWithInteger:yearIndex], 169 [NSNumber numberWithInteger:monthIndex], 170 [NSNumber numberWithInteger:dayIndex], 171 [NSNumber numberWithInteger:hourIndex], 172 [NSNumber numberWithInteger:minuteIndex] 173 ]; 174 break; 175 } 176 case KMDatePickerStyleYearMonthDay: { 177 arrIndex = @[ 178 [NSNumber numberWithInteger:yearIndex], 179 [NSNumber numberWithInteger:monthIndex], 180 [NSNumber numberWithInteger:dayIndex] 181 ]; 182 break; 183 } 184 case KMDatePickerStyleMonthDayHourMinute: { 185 arrIndex = @[ 186 [NSNumber numberWithInteger:monthIndex], 187 [NSNumber numberWithInteger:dayIndex], 188 [NSNumber numberWithInteger:hourIndex], 189 [NSNumber numberWithInteger:minuteIndex] 190 ]; 191 break; 192 } 193 case KMDatePickerStyleHourMinute: { 194 arrIndex = @[ 195 [NSNumber numberWithInteger:hourIndex], 196 [NSNumber numberWithInteger:minuteIndex] 197 ]; 198 break; 199 } 200 } 201 202 for (NSUInteger i=0, len=arrIndex.count; i<len; i++) { 203 [pikV selectRow:[arrIndex[i] integerValue] inComponent:i animated:YES]; 204 } 205 } 206 207 - (BOOL)validatedDate:(NSDate *)date { 208 NSString *minDateStr = [NSString stringWithFormat:@"%@-%@-%@ %@:%@", 209 datePickerDateMinLimited.year, 210 datePickerDateMinLimited.month, 211 datePickerDateMinLimited.day, 212 datePickerDateMinLimited.hour, 213 datePickerDateMinLimited.minute 214 ]; 215 216 return !([date compare:[DateHelper dateFromString:minDateStr withFormat:nil]] == NSOrderedAscending || 217 [date compare:_maxLimitedDate] == NSOrderedDescending); 218 } 219 220 - (BOOL)canShowScrollToNowButton { 221 return [self validatedDate:[DateHelper localeDate]]; 222 } 223 224 - (void)cancel:(UIButton *)sender { 225 UIViewController *delegateVC = (UIViewController *)self.delegate; 226 [delegateVC.view endEditing:YES]; 227 } 228 229 - (void)scrollToNowDateIndexPosition:(UIButton *)sender { 230 //为了区别最大最小限制范围外行的标签颜色,这里需要重新加载所有组件列 231 [pikV reloadAllComponents]; 232 233 _scrollToDate = [DateHelper localeDate]; 234 datePickerDateScrollTo = [[KMDatePickerDateModel alloc] initWithDate:_scrollToDate]; 235 yearIndex = [datePickerDateScrollTo.year integerValue] - [datePickerDateMinLimited.year integerValue]; 236 monthIndex = [datePickerDateScrollTo.month integerValue] - 1; 237 dayIndex = [datePickerDateScrollTo.day integerValue] - 1; 238 hourIndex = [datePickerDateScrollTo.hour integerValue]; 239 minuteIndex = [datePickerDateScrollTo.minute integerValue]; 240 [self scrollToDateIndexPosition]; 241 } 242 243 - (void)confirm:(UIButton *)sender { 244 [self playDelegateAfterSelectedRow]; 245 246 [self cancel:sender]; 247 } 248 249 - (UIColor *)monthRowTextColor:(NSInteger)row { 250 UIColor *color = kRowNormalStatusColor; 251 NSString *dateStr = [NSString stringWithFormat:@"%@-%@-01 00:00", 252 mArrYear[yearIndex], 253 mArrMonth[row] 254 ]; 255 NSDate *date = [DateHelper dateFromString:dateStr withFormat:nil]; 256 257 NSString *minDateStr = [NSString stringWithFormat:@"%@-%@-01 00:00", 258 datePickerDateMinLimited.year, 259 datePickerDateMinLimited.month 260 ]; 261 262 if ([date compare:[DateHelper dateFromString:minDateStr withFormat:nil]] == NSOrderedAscending || 263 [date compare:_maxLimitedDate] == NSOrderedDescending) { 264 color = kRowDisabledStatusColor; 265 } 266 267 return color; 268 } 269 270 - (UIColor *)dayRowTextColor:(NSInteger)row { 271 UIColor *color = kRowNormalStatusColor; 272 NSString *dateStr = [NSString stringWithFormat:@"%@-%@-%@ 00:00", 273 mArrYear[yearIndex], 274 mArrMonth[monthIndex], 275 mArrDay[row] 276 ]; 277 NSDate *date = [DateHelper dateFromString:dateStr withFormat:nil]; 278 279 NSString *minDateStr = [NSString stringWithFormat:@"%@-%@-%@ 00:00", 280 datePickerDateMinLimited.year, 281 datePickerDateMinLimited.month, 282 datePickerDateMinLimited.day 283 ]; 284 285 if ([date compare:[DateHelper dateFromString:minDateStr withFormat:nil]] == NSOrderedAscending || 286 [date compare:_maxLimitedDate] == NSOrderedDescending) { 287 color = kRowDisabledStatusColor; 288 } 289 290 return color; 291 } 292 293 - (UIColor *)hourRowTextColor:(NSInteger)row { 294 UIColor *color = kRowNormalStatusColor; 295 NSString *dateStr = [NSString stringWithFormat:@"%@-%@-%@ %@:00", 296 mArrYear[yearIndex], 297 mArrMonth[monthIndex], 298 mArrDay[dayIndex], 299 mArrHour[row] 300 ]; 301 NSDate *date = [DateHelper dateFromString:dateStr withFormat:nil]; 302 303 NSString *minDateStr = [NSString stringWithFormat:@"%@-%@-%@ %@:00", 304 datePickerDateMinLimited.year, 305 datePickerDateMinLimited.month, 306 datePickerDateMinLimited.day, 307 datePickerDateMinLimited.hour 308 ]; 309 310 if ([date compare:[DateHelper dateFromString:minDateStr withFormat:nil]] == NSOrderedAscending || 311 [date compare:_maxLimitedDate] == NSOrderedDescending) { 312 color = kRowDisabledStatusColor; 313 } 314 315 return color; 316 } 317 318 - (UIColor *)minuteRowTextColor:(NSInteger)row { 319 NSString *format = @"yyyy-MM-dd HH:mm:ss"; 320 UIColor *color = kRowNormalStatusColor; 321 NSString *dateStr = [NSString stringWithFormat:@"%@-%@-%@ %@:%@:00", 322 mArrYear[yearIndex], 323 mArrMonth[monthIndex], 324 mArrDay[dayIndex], 325 mArrHour[hourIndex], 326 mArrMinute[row] 327 ]; 328 NSDate *date = [DateHelper dateFromString:dateStr withFormat:format]; 329 330 NSString *minDateStr = [NSString stringWithFormat:@"%@-%@-%@ %@:%@:00", 331 datePickerDateMinLimited.year, 332 datePickerDateMinLimited.month, 333 datePickerDateMinLimited.day, 334 datePickerDateMinLimited.hour, 335 datePickerDateMinLimited.minute 336 ]; 337 338 if ([date compare:[DateHelper dateFromString:minDateStr withFormat:format]] == NSOrderedAscending || 339 [date compare:_maxLimitedDate] == NSOrderedDescending) { 340 color = kRowDisabledStatusColor; 341 } 342 343 return color; 344 } 345 346 #pragma mark - 绘制内容 347 - (void)drawRect:(CGRect)rect { 348 //加载数据 349 [self loadData]; 350 351 //初始化头部按钮(取消、现在时间、确定) 352 UIView *buttonContentView = [[UIView alloc] initWithFrame:CGRectMake(-2.0, 0.0, kWidthOfTotal + 4.0, kHeightOfButtonContentView)]; 353 buttonContentView.layer.borderColor = [UIColor lightGrayColor].CGColor; 354 buttonContentView.layer.borderWidth = 0.5; 355 [self addSubview:buttonContentView]; 356 357 UIButton *btnCancel = [UIButton buttonWithType:UIButtonTypeCustom]; 358 btnCancel.frame = CGRectMake(2.0, 2.5, 60.0, kHeightOfButtonContentView - 5.0); 359 btnCancel.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; 360 [btnCancel setTitle:@"取消" forState:UIControlStateNormal]; 361 [btnCancel setTitleColor:kButtonNormalStatusColor forState:UIControlStateNormal]; 362 [btnCancel addTarget:self 363 action:@selector(cancel:) 364 forControlEvents:UIControlEventTouchUpInside]; 365 [buttonContentView addSubview:btnCancel]; 366 367 if ([self canShowScrollToNowButton]) { 368 UIButton *btnScrollToNow = [UIButton buttonWithType:UIButtonTypeCustom]; 369 btnScrollToNow.frame = CGRectMake(buttonContentView.frame.size.width/2 - 50.0, 2.5, 100.0, kHeightOfButtonContentView - 5.0); 370 btnScrollToNow.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; 371 [btnScrollToNow setTitle:@"现在时间" forState:UIControlStateNormal]; 372 [btnScrollToNow setTitleColor:kButtonNormalStatusColor forState:UIControlStateNormal]; 373 [btnScrollToNow addTarget:self 374 action:@selector(scrollToNowDateIndexPosition:) 375 forControlEvents:UIControlEventTouchUpInside]; 376 [buttonContentView addSubview:btnScrollToNow]; 377 } 378 379 UIButton *btnConfirm = [UIButton buttonWithType:UIButtonTypeCustom]; 380 btnConfirm.frame = CGRectMake(kWidthOfTotal - 58.0, 2.5, 60.0, kHeightOfButtonContentView - 5.0); 381 btnConfirm.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; 382 [btnConfirm setTitle:@"确定" forState:UIControlStateNormal]; 383 [btnConfirm setTitleColor:kButtonNormalStatusColor forState:UIControlStateNormal]; 384 [btnConfirm addTarget:self 385 action:@selector(confirm:) 386 forControlEvents:UIControlEventTouchUpInside]; 387 [buttonContentView addSubview:btnConfirm]; 388 389 //初始化选择器视图控件 390 if (!pikV) { 391 pikV = [[UIPickerView alloc]initWithFrame:CGRectMake(0.0, kHeightOfButtonContentView, kWidthOfTotal, self.frame.size.height - kHeightOfButtonContentView)]; 392 pikV.showsSelectionIndicator = YES; 393 pikV.backgroundColor = [UIColor clearColor]; 394 [self addSubview:pikV]; 395 } 396 pikV.dataSource = self; 397 pikV.delegate = self; 398 399 //初始化滚动到指定时间位置 400 [self scrollToDateIndexPosition]; 401 } 402 403 #pragma mark - 执行 KMDatePickerDelegate 委托代理协议方法,用于回调传递参数 404 - (void)playDelegateAfterSelectedRow { 405 if ([self.delegate respondsToSelector:@selector(datePicker:didSelectDate:)]) { 406 [self.delegate datePicker:self 407 didSelectDate:datePickerDateScrollTo]; 408 } 409 } 410 411 #pragma mark - UIPickerViewDataSource 412 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 413 NSInteger numberOfComponents = 0; 414 switch (_datePickerStyle) { 415 case KMDatePickerStyleYearMonthDayHourMinute: { 416 numberOfComponents = 5; 417 break; 418 } 419 case KMDatePickerStyleYearMonthDay: { 420 numberOfComponents = 3; 421 break; 422 } 423 case KMDatePickerStyleMonthDayHourMinute: { 424 numberOfComponents = 4; 425 break; 426 } 427 case KMDatePickerStyleHourMinute: { 428 numberOfComponents = 2; 429 break; 430 } 431 } 432 return numberOfComponents; 433 } 434 435 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 436 NSInteger numberOfRows = 0; 437 switch (_datePickerStyle) { 438 case KMDatePickerStyleYearMonthDayHourMinute: { 439 switch (component) { 440 case 0: 441 numberOfRows = mArrYear.count; 442 break; 443 case 1: 444 numberOfRows = kMonthCountOfEveryYear; 445 break; 446 case 2: 447 numberOfRows = [self daysOfMonth]; 448 break; 449 case 3: 450 numberOfRows = kHourCountOfEveryDay; 451 break; 452 case 4: 453 numberOfRows = kMinuteCountOfEveryHour; 454 break; 455 } 456 break; 457 } 458 case KMDatePickerStyleYearMonthDay: { 459 switch (component) { 460 case 0: 461 numberOfRows = mArrYear.count; 462 break; 463 case 1: 464 numberOfRows = kMonthCountOfEveryYear; 465 break; 466 case 2: 467 numberOfRows = [self daysOfMonth]; 468 break; 469 } 470 break; 471 } 472 case KMDatePickerStyleMonthDayHourMinute: { 473 switch (component) { 474 case 0: 475 numberOfRows = kMonthCountOfEveryYear; 476 break; 477 case 1: 478 numberOfRows = [self daysOfMonth]; 479 break; 480 case 2: 481 numberOfRows = kHourCountOfEveryDay; 482 break; 483 case 3: 484 numberOfRows = kMinuteCountOfEveryHour; 485 break; 486 } 487 break; 488 } 489 case KMDatePickerStyleHourMinute: { 490 switch (component) { 491 case 0: 492 numberOfRows = kHourCountOfEveryDay; 493 break; 494 case 1: 495 numberOfRows = kMinuteCountOfEveryHour; 496 break; 497 } 498 break; 499 } 500 } 501 return numberOfRows; 502 } 503 504 #pragma mark - UIPickerViewDelegate 505 - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component { 506 CGFloat width = 50.0; 507 CGFloat widthOfAverage; 508 509 switch (_datePickerStyle) { 510 case KMDatePickerStyleYearMonthDayHourMinute: { 511 //规则一:平均宽度 = (总共宽度 - 年份相比多两个数字的宽度 - 分钟会是右对齐导致需偏移宽度来显示「分」这个文字) / 5等份 512 widthOfAverage = (kWidthOfTotal - 20.0 - 25.0) / 5; 513 switch (component) { 514 case 0: 515 width = widthOfAverage + 20.0; 516 //规则二:单位标签的 X 坐标位置 = 列的水平居中 X 坐标 + 偏移量 517 [self addUnitLabel:@"年" withPointX:width/2 + 24.0]; 518 break; 519 case 1: 520 width = widthOfAverage; 521 [self addUnitLabel:@"月" withPointX:(widthOfAverage + 20.0) + width/2 + 16.0]; 522 break; 523 case 2: 524 width = widthOfAverage; 525 [self addUnitLabel:@"日" withPointX:(2*widthOfAverage + 20.0) + width/2 + 22.0]; 526 break; 527 case 3: 528 width = widthOfAverage; 529 [self addUnitLabel:@"时" withPointX:(3*widthOfAverage + 20.0) + width/2 + 28.0]; 530 break; 531 case 4: 532 width = widthOfAverage; 533 [self addUnitLabel:@"分" withPointX:(4*widthOfAverage + 20.0) + width/2 + 32.0]; 534 break; 535 } 536 break; 537 } 538 case KMDatePickerStyleYearMonthDay: { 539 widthOfAverage = (kWidthOfTotal - 20.0 - 15.0) / 3; 540 switch (component) { 541 case 0: 542 width = widthOfAverage + 20.0; 543 [self addUnitLabel:@"年" withPointX:width/2 + 24.0]; 544 break; 545 case 1: 546 width = widthOfAverage; 547 [self addUnitLabel:@"月" withPointX:(widthOfAverage + 20.0) + width/2 + 16.0]; 548 break; 549 case 2: 550 width = widthOfAverage; 551 [self addUnitLabel:@"日" withPointX:(2*widthOfAverage + 20.0) + width/2 + 22.0]; 552 break; 553 } 554 break; 555 } 556 case KMDatePickerStyleMonthDayHourMinute: { 557 widthOfAverage = (kWidthOfTotal - 20.0) / 4; 558 switch (component) { 559 case 0: 560 width = widthOfAverage; 561 [self addUnitLabel:@"月" withPointX:width/2 + 11.0]; 562 break; 563 case 1: 564 width = widthOfAverage; 565 [self addUnitLabel:@"日" withPointX:widthOfAverage + width/2 + 17.0]; 566 break; 567 case 2: 568 width = widthOfAverage; 569 [self addUnitLabel:@"时" withPointX:2*widthOfAverage + width/2 + 23.0]; 570 break; 571 case 3: 572 width = widthOfAverage; 573 [self addUnitLabel:@"分" withPointX:3*widthOfAverage + width/2 + 27.0]; 574 break; 575 } 576 break; 577 } 578 case KMDatePickerStyleHourMinute: { 579 widthOfAverage = (kWidthOfTotal - 10.0) / 2; 580 switch (component) { 581 case 0: 582 width = widthOfAverage; 583 [self addUnitLabel:@"时" withPointX:width/2 + 12.0]; 584 break; 585 case 1: 586 width = widthOfAverage; 587 [self addUnitLabel:@"分" withPointX:widthOfAverage + width/2 + 18.0]; 588 break; 589 } 590 break; 591 } 592 } 593 return width; 594 } 595 596 - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { 597 return 30.0; 598 } 599 600 - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view { 601 UILabel *lblCustom = (UILabel *)view; 602 if (!lblCustom) { 603 lblCustom = [UILabel new]; 604 lblCustom.textAlignment = NSTextAlignmentCenter; 605 lblCustom.font = [UIFont systemFontOfSize:18.0]; 606 } 607 608 NSString *text; 609 UIColor *textColor = kRowNormalStatusColor; 610 switch (_datePickerStyle) { 611 case KMDatePickerStyleYearMonthDayHourMinute: { 612 switch (component) { 613 case 0: 614 text = mArrYear[row]; 615 break; 616 case 1: 617 text = mArrMonth[row]; 618 textColor = [self monthRowTextColor:row]; 619 break; 620 case 2: 621 text = mArrDay[row]; 622 textColor = [self dayRowTextColor:row]; 623 break; 624 case 3: 625 text = mArrHour[row]; 626 textColor = [self hourRowTextColor:row]; 627 break; 628 case 4: 629 text = mArrMinute[row]; 630 textColor = [self minuteRowTextColor:row]; 631 break; 632 } 633 break; 634 } 635 case KMDatePickerStyleYearMonthDay: { 636 switch (component) { 637 case 0: 638 text = mArrYear[row]; 639 break; 640 case 1: 641 text = mArrMonth[row]; 642 textColor = [self monthRowTextColor:row]; 643 break; 644 case 2: 645 text = mArrDay[row]; 646 textColor = [self dayRowTextColor:row]; 647 break; 648 } 649 break; 650 } 651 case KMDatePickerStyleMonthDayHourMinute: { 652 switch (component) { 653 case 0: 654 text = mArrMonth[row]; 655 textColor = [self monthRowTextColor:row]; 656 break; 657 case 1: 658 text = mArrDay[row]; 659 textColor = [self dayRowTextColor:row]; 660 break; 661 case 2: 662 text = mArrHour[row]; 663 textColor = [self hourRowTextColor:row]; 664 break; 665 case 3: 666 text = mArrMinute[row]; 667 textColor = [self minuteRowTextColor:row]; 668 break; 669 } 670 break; 671 } 672 case KMDatePickerStyleHourMinute: { 673 switch (component) { 674 case 0: 675 text = mArrHour[row]; 676 textColor = [self hourRowTextColor:row]; 677 break; 678 case 1: 679 text = mArrMinute[row]; 680 textColor = [self minuteRowTextColor:row]; 681 break; 682 } 683 break; 684 } 685 } 686 lblCustom.text = text; 687 lblCustom.textColor = textColor; 688 return lblCustom; 689 } 690 691 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 692 NSDate *scrollToDateTemp = _scrollToDate; 693 KMDatePickerDateModel *datePickerDateScrollToTemp = datePickerDateScrollTo; 694 695 switch (_datePickerStyle) { 696 case KMDatePickerStyleYearMonthDayHourMinute: { 697 switch (component) { 698 case 0: 699 yearIndex = row; 700 break; 701 case 1: 702 monthIndex = row; 703 break; 704 case 2: 705 dayIndex = row; 706 break; 707 case 3: 708 hourIndex = row; 709 break; 710 case 4: 711 minuteIndex = row; 712 break; 713 } 714 if (component == 0 || component == 1) { 715 [self reloadDayArray]; 716 if (mArrDay.count-1 < dayIndex) { 717 dayIndex = mArrDay.count-1; 718 } 719 //[pickerView reloadComponent:2]; 720 } 721 break; 722 } 723 case KMDatePickerStyleYearMonthDay: { 724 switch (component) { 725 case 0: 726 yearIndex = row; 727 break; 728 case 1: 729 monthIndex = row; 730 break; 731 case 2: 732 dayIndex = row; 733 break; 734 } 735 if (component == 0 || component == 1) { 736 [self reloadDayArray]; 737 if (mArrDay.count-1 < dayIndex) { 738 dayIndex = mArrDay.count-1; 739 } 740 //[pickerView reloadComponent:2]; 741 } 742 break; 743 } 744 case KMDatePickerStyleMonthDayHourMinute: { 745 switch (component) { 746 case 0: 747 monthIndex = row; 748 break; 749 case 1: 750 dayIndex = row; 751 break; 752 case 2: 753 hourIndex = row; 754 break; 755 case 3: 756 minuteIndex = row; 757 break; 758 } 759 if (component == 0) { 760 [self reloadDayArray]; 761 if (mArrDay.count-1 < dayIndex) { 762 dayIndex = mArrDay.count-1; 763 } 764 //[pickerView reloadComponent:1]; 765 } 766 break; 767 } 768 case KMDatePickerStyleHourMinute: { 769 switch (component) { 770 case 0: 771 hourIndex = row; 772 break; 773 case 1: 774 minuteIndex = row; 775 break; 776 } 777 break; 778 } 779 } 780 781 NSString *dateStr = [NSString stringWithFormat:@"%@-%@-%@ %@:%@", 782 mArrYear[yearIndex], 783 mArrMonth[monthIndex], 784 mArrDay[dayIndex], 785 mArrHour[hourIndex], 786 mArrMinute[minuteIndex] 787 ]; 788 _scrollToDate = [DateHelper dateFromString:dateStr withFormat:nil]; 789 datePickerDateScrollTo = [[KMDatePickerDateModel alloc] initWithDate:_scrollToDate]; 790 791 //为了区别最大最小限制范围外行的标签颜色,这里需要重新加载所有组件列 792 [pickerView reloadAllComponents]; 793 794 //如果选择时间不在最小和最大限制时间范围内就回滚 795 if (![self validatedDate:_scrollToDate]) { 796 _scrollToDate = scrollToDateTemp; 797 datePickerDateScrollTo = datePickerDateScrollToTemp; 798 yearIndex = [datePickerDateScrollTo.year integerValue] - [datePickerDateMinLimited.year integerValue]; 799 monthIndex = [datePickerDateScrollTo.month integerValue] - 1; 800 dayIndex = [datePickerDateScrollTo.day integerValue] - 1; 801 hourIndex = [datePickerDateScrollTo.hour integerValue]; 802 minuteIndex = [datePickerDateScrollTo.minute integerValue]; 803 [self scrollToDateIndexPosition]; 804 } 805 } 806 807 @end
源码下载地址:
https://github.com/KenmuHuang/KMDatePicker