
支持四种格式,可控制可选时间范围,如下:
(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>View Code
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 @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 @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