KBDatePickerView.m 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #import "KBDatePickerView.h"
  2. @interface KBDatePickerView () {
  3. NSDate *_currentDate;
  4. }
  5. @property UIStackView *datePickerStackView;
  6. @property UITableView *monthTable;
  7. @property UITableView *dayTable;
  8. @property UITableView *yearTable;
  9. @property UILabel *monthLabel;
  10. @property UILabel *dayLabel;
  11. @property UILabel *yearLabel;
  12. @end
  13. @implementation KBDatePickerView
  14. - (NSDate *)date {
  15. if (!_currentDate){
  16. [self setDate:[NSDate date]];
  17. }
  18. return _currentDate;
  19. }
  20. - (NSCalendar *)calendar {
  21. return [NSCalendar currentCalendar];
  22. }
  23. - (void)setDate:(NSDate *)date {
  24. _currentDate = date;
  25. //_dateLabel.text = date.description;
  26. [self scrollToCurrentDateAnimated:true];
  27. }
  28. - (id)init {
  29. self = [super init];
  30. if (![self date]){
  31. [self setDate:[NSDate date]];
  32. }
  33. [self layoutViews];
  34. return self;
  35. }
  36. - (void)scrollToCurrentDateAnimated:(BOOL)animated {
  37. NSDateComponents *components = [[self calendar] components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self.date];
  38. [_monthTable selectRowAtIndexPath:[NSIndexPath indexPathForRow:components.month-1 inSection:0] animated:animated scrollPosition:UITableViewScrollPositionTop];
  39. [_dayTable selectRowAtIndexPath:[NSIndexPath indexPathForRow:components.day-1 inSection:0] animated:animated scrollPosition:UITableViewScrollPositionTop];
  40. [_yearTable selectRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0] animated:animated scrollPosition:UITableViewScrollPositionTop];
  41. }
  42. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  43. if (tableView == _monthTable){
  44. return [self calendar].monthSymbols.count;
  45. } else if (tableView == _dayTable){
  46. NSRange days = [[self calendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:self.date];
  47. return days.length;
  48. } else {
  49. return 3;
  50. }
  51. }
  52. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  53. UITableViewCell *cell = nil;
  54. if (tableView == _monthTable){
  55. cell = [tableView dequeueReusableCellWithIdentifier:@"month"];
  56. if (!cell){
  57. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"month"];
  58. }
  59. cell.textLabel.text = [[self calendar] monthSymbols][indexPath.row];
  60. cell.textLabel.textAlignment = NSTextAlignmentCenter;
  61. } else if (tableView == _dayTable){
  62. cell = [tableView dequeueReusableCellWithIdentifier:@"day"];
  63. if (!cell){
  64. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"day"];
  65. }
  66. cell.textLabel.text = [NSString stringWithFormat:@"%lu", indexPath.row + 1];
  67. cell.textLabel.textAlignment = NSTextAlignmentCenter;
  68. } else {
  69. cell = [tableView dequeueReusableCellWithIdentifier:@"year"];
  70. if (!cell){
  71. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"year"];
  72. }
  73. NSInteger year = [[self calendar] component:NSCalendarUnitYear fromDate:self.date];
  74. cell.textLabel.text = [NSString stringWithFormat:@"%lu", year - 1 + indexPath.row];
  75. cell.textLabel.textAlignment = NSTextAlignmentCenter;
  76. }
  77. return cell;
  78. }
  79. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  80. NSDateComponents *components = [[self calendar] components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self.date];
  81. if (tableView == _monthTable){
  82. NSInteger month = indexPath.row + 1;
  83. components.month = month;
  84. NSDate *newDate = nil;
  85. do {
  86. newDate = [[self calendar] dateFromComponents:components];
  87. components.day -= 1;
  88. } while (newDate == nil || ([[self calendar] component:NSCalendarUnitMonth fromDate:newDate] != month));
  89. [self setDate:newDate];
  90. [[self dayTable] reloadData];
  91. [[self yearTable] reloadData];
  92. } else if (tableView == _dayTable){
  93. components.day = indexPath.row + 1;
  94. NSDate *newDate = [[self calendar] dateFromComponents:components];
  95. if (newDate){
  96. [self setDate:newDate];
  97. [[self monthTable] reloadData];
  98. [[self yearTable] reloadData];
  99. }
  100. } else {
  101. NSInteger year = [[self calendar] component:NSCalendarUnitYear fromDate:self.date];
  102. components.year = year - 1 + indexPath.row;
  103. NSDate *newDate = nil;
  104. do {
  105. newDate = [[self calendar] dateFromComponents:components];
  106. components.day -= 1;
  107. } while (newDate == nil || ([[self calendar] component:NSCalendarUnitMonth fromDate:newDate] != components.month));
  108. [self setDate:newDate];
  109. [[self monthTable] reloadData];
  110. [[self yearTable] reloadData];
  111. }
  112. if (self.itemSelectedBlock){
  113. self.itemSelectedBlock(self.date);
  114. }
  115. }
  116. - (CGSize)sizeThatFits:(CGSize)size {
  117. CGSize sup = [super sizeThatFits:size];
  118. return CGSizeMake(720, 128+81+60+40);
  119. }
  120. - (void)layoutViews {
  121. self.monthLabel = [[UILabel alloc] init];
  122. self.monthLabel.translatesAutoresizingMaskIntoConstraints = false;
  123. self.monthLabel.text = @"Month";
  124. self.yearLabel = [[UILabel alloc] init];
  125. self.yearLabel.translatesAutoresizingMaskIntoConstraints = false;
  126. self.yearLabel.text = @"Year";
  127. self.dayLabel = [[UILabel alloc] init];
  128. self.dayLabel.translatesAutoresizingMaskIntoConstraints = false;
  129. self.dayLabel.text = @"Day";
  130. self.monthTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
  131. self.yearTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
  132. self.dayTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
  133. self.monthTable.delegate = self;
  134. self.monthTable.dataSource = self;
  135. self.yearTable.delegate = self;
  136. self.yearTable.dataSource = self;
  137. self.dayTable.delegate = self;
  138. self.dayTable.dataSource = self;
  139. self.datePickerStackView = [[UIStackView alloc] initWithArrangedSubviews:@[self.monthTable, self.dayTable, self.yearTable]];
  140. self.datePickerStackView.translatesAutoresizingMaskIntoConstraints = false;
  141. self.datePickerStackView.spacing = 10;
  142. self.datePickerStackView.axis = UILayoutConstraintAxisHorizontal;
  143. self.datePickerStackView.alignment = UIStackViewAlignmentFill;
  144. self.datePickerStackView.distribution = UIStackViewDistributionFillEqually;
  145. [self.datePickerStackView.widthAnchor constraintEqualToConstant:720].active = true;
  146. [self.datePickerStackView.heightAnchor constraintEqualToConstant:128].active = true;
  147. [self addSubview:self.datePickerStackView];
  148. [self addSubview:self.monthLabel];
  149. [self addSubview:self.yearLabel];
  150. [self addSubview:self.dayLabel];
  151. [self.datePickerStackView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor].active = true;
  152. [self.datePickerStackView.topAnchor constraintEqualToAnchor:self.dayLabel.bottomAnchor constant:60].active = true;
  153. [self.monthLabel.topAnchor constraintEqualToAnchor:self.topAnchor constant:20].active = true;
  154. [self.dayLabel.topAnchor constraintEqualToAnchor:self.topAnchor constant:20].active = true;
  155. [self.dayLabel.centerXAnchor constraintEqualToAnchor:self.dayTable.centerXAnchor].active = true;
  156. [self.monthLabel.centerXAnchor constraintEqualToAnchor:self.monthTable.centerXAnchor].active = true;
  157. [self.yearLabel.centerXAnchor constraintEqualToAnchor:self.yearTable.centerXAnchor].active = true;
  158. [self.yearLabel.topAnchor constraintEqualToAnchor:self.topAnchor constant:20].active = true;
  159. [self.monthLabel.topAnchor constraintEqualToAnchor:self.topAnchor constant:20].active = true;
  160. }
  161. @end