自定义时间选择器,时间到今天为止,并且可设置显示的年的数量
使用:
- (DatePickerView *)datePickerView {
if (!_datePickerView) {
NSInteger count = [[NSDate date] getYear] - 2017;
_datePickerView = [[DatePickerView alloc] initWithType:DatePickerViewTypeYearMonth showYears:count];
_datePickerView.delegate = self;
}
return _datePickerView;
}
效果:
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, DatePickerViewType) {
DatePickerViewTypeYear,
DatePickerViewTypeYearMonth,
DatePickerViewTypeYearMonthDay
};
@protocol DatePickerViewDelegate<NSObject>
- (void)datePickerViewDidCancel;
- (void)datePickerViewDidSelect:(NSInteger)year and:(NSInteger)month and:(NSInteger)day;
@end
@interface DatePickerView : UIView
@property (nonatomic, weak) id<DatePickerViewDelegate> delegate;
@property (nonatomic, assign) DatePickerViewType type;
- (instancetype)initWithType:(DatePickerViewType)type showYears:(NSInteger)count;
- (instancetype)initWithType:(DatePickerViewType)type showYears:(NSInteger)count image:(NSString *)name;
- (void)showInView:(UIView *)view;
- (void)dismiss;
@end
#import "DatePickerView.h"
@interface DatePickerView() <UIPickerViewDataSource,UIPickerViewDelegate>
{
NSDateComponents *currentDateComponents;
NSInteger maxYearCount;
CGFloat pickerViewHeight;
UIView *contentView;
UIImageView *imageView;
}
@property (nonatomic, strong) UIPickerView *pickerView;
@property (nonatomic, strong) UIDatePicker *datePicker;
@property (nonatomic, strong) NSMutableArray<NSMutableArray<NSString *> *> * dataArray;
@end
@implementation DatePickerView
- (UIPickerView *)pickerView {
if (!_pickerView) {
_pickerView = [[UIPickerView alloc] init];
_pickerView.delegate = self;
_pickerView.dataSource = self;
}
return _pickerView;
}
- (instancetype)init {
return [self initWithType:DatePickerViewTypeYearMonthDay showYears:50 image:nil];
}
- (instancetype)initWithType:(DatePickerViewType)type showYears:(NSInteger)count
{
return [self initWithType:type showYears:count image:nil];
}
- (instancetype)initWithType:(DatePickerViewType)type showYears:(NSInteger)count image:(NSString *)name
{
self.type = type;
self = [super initWithFrame:ScreenBounds];
if (self) {
[self initViewWithShowYears:count image:name];
}
return self;
}
- (void)initViewWithShowYears:(NSInteger)count image:(NSString *)name {
count = count > 0 ? count : 3;
maxYearCount = count;
pickerViewHeight = 240 * ScaleWidth + 40;
self.backgroundColor = Color_Background_Alpha;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)];
[self addGestureRecognizer:tap];
if (name) {
//显示例图
UIImage *image = [UIImage imageNamed:name];
imageView = [[UIImageView alloc] initWithImage:image];
CGFloat width = ScreenWidth - 38 * 2;
CGFloat height = width / 3 * 2;
imageView.frame = CGRectMake(38, ScreenHeight - pickerViewHeight - height - 50, width, height);
imageView.alpha = 0;
[self addSubview:imageView];
}
contentView = [[UIView alloc] initWithFrame:CGRectMake(0, ScreenHeight, ScreenWidth, pickerViewHeight)];
contentView.backgroundColor = Color_Background;
[self addSubview:contentView];
UIButton *cancelButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 80, 44)];
[cancelButton setTitle:@"取消" forState:UIControlStateNormal];
[cancelButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
cancelButton.titleLabel.font = [UIFont boldSystemFontOfSize:16];
[cancelButton addTarget:self action:@selector(cancelButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[contentView addSubview:cancelButton];
UIButton *confirmButton = [[UIButton alloc] initWithFrame:CGRectMake(ScreenWidth - 80, 0, 80, 44)];
[confirmButton setTitle:@"确认" forState:UIControlStateNormal];
[confirmButton setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];
confirmButton.titleLabel.font = [UIFont boldSystemFontOfSize:16];
[confirmButton addTarget:self action:@selector(confirmButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[contentView addSubview:confirmButton];
NSCalendar *calendar = [NSCalendar currentCalendar];
unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
currentDateComponents = [calendar components:unitFlags fromDate:[NSDate date]];
NSLog(@"现在时间:%ld年 %ld月 %ld日", (long)currentDateComponents.year, (long)currentDateComponents.month, (long)currentDateComponents.day);
//当前时间的行
NSInteger yearIndex = maxYearCount - 1;
NSInteger monthIndex = currentDateComponents.month - 1;
NSInteger dayIndex = currentDateComponents.day - 1;
//数据源
_dataArray = [[NSMutableArray alloc] initWithCapacity:0];
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:0];
for (int i = 0; i <= yearIndex; i ++) {
[arr addObject:[NSString stringWithFormat:@"%zd年", currentDateComponents.year - maxYearCount + i + 1]];
}
[_dataArray addObject:arr];
if (self.type != DatePickerViewTypeYear) {
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:0];
for (int i = 0; i <= monthIndex; i ++) {
[arr addObject:[NSString stringWithFormat:@"%d月", i + 1]];
}
[_dataArray addObject:arr];
}
if (self.type == DatePickerViewTypeYearMonthDay) {
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:0];
for (int i = 0; i <= dayIndex; i ++) {
[arr addObject:[NSString stringWithFormat:@"%d日", i + 1]];
}
[_dataArray addObject:arr];
}
//初始化选中的行
[self.pickerView selectRow:yearIndex inComponent:0 animated:YES];
if (self.type != DatePickerViewTypeYear) {
[self.pickerView selectRow:monthIndex inComponent:1 animated:YES];
}
if (self.type == DatePickerViewTypeYearMonthDay) {
[self.pickerView selectRow:dayIndex inComponent:2 animated:YES];
}
self.pickerView.frame = CGRectMake(0, 40, ScreenWidth, pickerViewHeight - 40);
[contentView addSubview:self.pickerView];
}
- (void)tapAction {
[self dismiss];
}
- (void)cancelButtonAction:(UIButton *)sender {
if ([self.delegate respondsToSelector:@selector(datePickerViewDidCancel)]) {
[self.delegate datePickerViewDidCancel];
}
[self dismiss];
}
- (void)confirmButtonAction:(UIButton *)sender {
NSInteger currentYear = currentDateComponents.year - maxYearCount + [self.pickerView selectedRowInComponent:0] + 1;
NSInteger currentMonth = 0;
NSInteger currentDay = 0;
if (self.type != DatePickerViewTypeYear) {
currentMonth = [self.pickerView selectedRowInComponent:1] + 1;
}
if (self.type == DatePickerViewTypeYearMonthDay) {
currentDay = [self.pickerView selectedRowInComponent:2] + 1;
}
NSLog(@"选择时间:%ld年 %ld月 %ld日", (long)currentYear, (long)currentMonth, (long)currentDay);
if ([self.delegate respondsToSelector:@selector(datePickerViewDidSelect:and:and:)]) {
[self.delegate datePickerViewDidSelect:currentYear and:currentMonth and:currentDay];
}
[self dismiss];
}
- (void)showInView:(UIView *)view {
[view addSubview:self];
__weak typeof(self) weakSelf = self;
[UIView animateWithDuration:TimeInterval_Animation animations:^{
CGRect frame = self->contentView.frame;
frame.origin.y = ScreenHeight - self->pickerViewHeight;
self->contentView.frame = frame;
self->imageView.alpha = 1;
[weakSelf layoutIfNeeded];
}];
}
- (void)dismiss {
__weak typeof(self) weakSelf = self;
[UIView animateWithDuration:TimeInterval_Animation animations:^{
CGRect frame = self->contentView.frame;
frame.origin.y = ScreenHeight;
self->contentView.frame = frame;
self->imageView.alpha = 0;
[weakSelf layoutIfNeeded];
} completion:^(BOOL finished) {
if (finished) {
[weakSelf removeFromSuperview];
}
}];
}
#pragma mark - DelegateAndDataSource
//列数
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return self.dataArray.count;
}
//行数
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return self.dataArray[component].count;
}
//每一列的宽度
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
return ScreenWidth / 4;
}
//每一行的高度
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {
return 30;
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel *label = [[UILabel alloc] init];
label.font = [UIFont boldSystemFontOfSize:20];
label.textAlignment = NSTextAlignmentCenter;
label.text = self.dataArray[component][row];
return label;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
//选中年月刷新对应的月日
if (self.type == DatePickerViewTypeYearMonthDay) {
if (component == 0) {
[self datePickReloadMonth];
[self datePickReloadDay];
} else if (component == 1) {
[self datePickReloadDay];
}
} else if (self.type == DatePickerViewTypeYearMonth) {
if (component == 0) {
[self datePickReloadMonth];
}
}
}
- (void)datePickReloadMonth {
NSInteger yearIndex = [self.pickerView selectedRowInComponent:0];
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:0];
NSInteger month = 12;
if (yearIndex == maxYearCount - 1) {
month = currentDateComponents.month;
}
for (int i = 0; i < month; i ++) {
[arr addObject:[NSString stringWithFormat:@"%d月", i + 1]];
}
[_dataArray replaceObjectAtIndex:1 withObject:arr];
[self.pickerView reloadComponent:1];
}
- (void)datePickReloadDay {
NSInteger yearIndex = [self.pickerView selectedRowInComponent:0];
NSInteger monthIndex = [self.pickerView selectedRowInComponent:1];
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:0];
NSInteger days = [self dayNumberOfYear:_dataArray[0][yearIndex].integerValue month:_dataArray[1][monthIndex].integerValue];
if (yearIndex == maxYearCount - 1 && monthIndex == currentDateComponents.month - 1) {
days = currentDateComponents.day;
}
for (int i = 0; i < days; i ++) {
[arr addObject:[NSString stringWithFormat:@"%d日", i + 1]];
}
[_dataArray replaceObjectAtIndex:2 withObject:arr];
[self.pickerView reloadComponent:2];
}
- (NSInteger)dayNumberOfYear:(NSInteger)year month:(NSInteger)month {
switch (month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
return 31;
case 4: case 6: case 9: case 11:
return 30;
default:
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
return 29;
} else {
return 28;
}
}
}
@end