300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 【iOS开发】—— 自定义选择器实现日期选择器

【iOS开发】—— 自定义选择器实现日期选择器

时间:2024-03-26 07:24:29

相关推荐

【iOS开发】—— 自定义选择器实现日期选择器

在写项目时,个人资料生日这一块,想写成QQ中使用的效果。然后就学了一下UIPickerView。

系统其实提供了一个日期选择器UIDatePicker,但是它的实现效果并不是我想要的

所以我自定义选择器来实现一个日期选择器。

设计思路

为了在点击时,背景为灰色,所以我打算将一个背景为灰色的图层加到主页面上,点击确定、取消和空白区域可以移除。再向此图层上加一个contentView。这个contentView上放取消按钮和确认按钮以及选择器。

代码:

BasePickerView.h#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN@interface BasePickerView : UIView@property (nonatomic, strong) UIView* contentView;//选择器@property (nonatomic, strong)UIPickerView *pickerView;//取消按钮@property (nonatomic, strong)UIButton *cancelButton;//确定按钮@property (nonatomic, strong)UIButton *confirmButton;//选择器的高度@property (nonatomic, assign)CGFloat pickerViewHeight;//创建视图,初始化视图时初始数据- (void)initPickView;//确认按钮的点击事件- (void)clickConfirmButton;//pickerView的显示- (void)show;//移除pickerView- (void)disMiss;@endNS_ASSUME_NONNULL_END

//BasePickerView.m#import "BasePickerView.h"#define ScreenWidth [UIScreen mainScreen].bounds.size.width#define ScreenHeight [UIScreen mainScreen].bounds.size.height@implementation BasePickerView- (instancetype)init {self = [super init];if(self) {_pickerViewHeight = 250;//设置此图层大小为主屏幕大小self.bounds = [UIScreen mainScreen].bounds;//设置背景为灰色self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];//定义手势,在点击空白区域时,移除此图层UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(disMiss)];self.userInteractionEnabled = YES;[self addGestureRecognizer:tap];//将内容视图加入此图层以及将选择器、确定按钮、取消按钮加入内容视图[self addSubview:self.contentView];[self.contentView addSubview:self.pickerView];[self.contentView addSubview:self.cancelButton];[self.contentView addSubview:self.confirmButton];//以便在子类中重写此方法,将pickerView所需的数据初始化[self initPickView];}return self;}- (void)initPickView {}//初始化内容视图- (UIView *)contentView{if (!_contentView) {_contentView = [[UIView alloc]initWithFrame:CGRectMake(0, ScreenHeight, ScreenWidth, self.pickerViewHeight)];[_contentView setBackgroundColor:[UIColor whiteColor]];}return _contentView;}//初始化选择器- (UIPickerView *)pickerView{if (!_pickerView) {_pickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(0, 0, self.contentView.frame.size.width, self.contentView.frame.size.height)];[_pickerView setBackgroundColor:[UIColor whiteColor]];}return _pickerView;}//初始化取消按钮- (UIButton *)cancelButton {if (!_cancelButton) {_cancelButton = [[UIButton alloc]initWithFrame:CGRectMake(16, 0, 44, 44)];[_cancelButton setTitle:@"取消" forState:UIControlStateNormal];[_cancelButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];[_cancelButton.titleLabel setFont:[UIFont systemFontOfSize:16]];[_cancelButton addTarget:self action:@selector(clickCancelButton) forControlEvents:UIControlEventTouchUpInside];}return _cancelButton;}//初始化确定按钮- (UIButton *)confirmButton {if (!_confirmButton) {_confirmButton = [[UIButton alloc]initWithFrame:CGRectMake(self.contentView.frame.size.width - self.cancelButton.frame.size.width - self.cancelButton.frame.origin.x, self.cancelButton.frame.origin.y, self.cancelButton.frame.size.width, self.cancelButton.frame.size.height)];[_confirmButton setTitle:@"确定" forState:UIControlStateNormal];[_confirmButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];[_confirmButton.titleLabel setFont:[UIFont systemFontOfSize:16]];[_confirmButton addTarget:self action:@selector(clickConfirmButton) forControlEvents:UIControlEventTouchUpInside];}return _confirmButton;}//等待继承他的子类重写此方法- (void)clickConfirmButton {[self disMiss];}- (void)clickCancelButton {[self disMiss];}//获取keyWindow- (UIWindow *)getKeyWindow {if (@available(iOS 13.0, *)) {for (UIWindowScene* windowScene in [UIApplication sharedApplication].connectedScenes) {if (windowScene.activationState == UISceneActivationStateForegroundActive) {for (UIWindow *window in windowScene.windows) {if (window.isKeyWindow){return window;break;}}}}} else {return [UIApplication sharedApplication].keyWindow;}return nil;}//移除此图层- (void)disMiss {CGRect frameContent = self.contentView.frame;// 相当于把contentView的y坐标设置为ScreenHeight,达到一个隐藏的目的frameContent.origin.y += self.contentView.frame.size.height;//设置动画效果[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{//将此图层不透明性设为0[self.layer setOpacity:0];// 再将内容视图隐藏self.contentView.frame = frameContent;} completion:^(BOOL finished) {//将此图层从父视图中移除掉[self removeFromSuperview];}];}//推出此图层- (void)show {[[self getKeyWindow] addSubview:self];[self setCenter:[self getKeyWindow].center];[[self getKeyWindow] bringSubviewToFront:self];CGRect frameContent = self.contentView.frame;frameContent.origin.y -= self.contentView.frame.size.height;[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{[self.layer setOpacity:1.0];self.contentView.frame = frameContent;} completion:nil];}@end

新建一个继承于BasePickerView的类,在这个类里实现UIPickerView数据源和代理方法,以及重写一些方法。

#import "BasePickerView.h"NS_ASSUME_NONNULL_BEGIN@class BasePickerView;@protocol DatePickerViewDelegate<NSObject> //定义一个代理。//此方法目的是得到当前选择器的选择结果- (void)pickerDateView:(BasePickerView *)pickerDateView selectYear:(NSInteger)year selectMonth:(NSInteger)month selectDay:(NSInteger)day;@end@interface DatePickerView : BasePickerView<UIPickerViewDelegate,UIPickerViewDataSource>@property(nonatomic, weak)id <DatePickerViewDelegate>delegate ;/** 选择的年 */@property (nonatomic, assign)NSInteger selectYear;/** 选择的月 */@property (nonatomic, assign)NSInteger selectMonth;/** 选择的日 */@property (nonatomic, assign)NSInteger selectDay;//现在的年月日@property (nonatomic, assign)NSInteger currentYear;@property (nonatomic, assign)NSInteger currentMonth;@property (nonatomic, assign)NSInteger currentDay;//默认年月日@property (nonatomic, assign)NSInteger defaultYear;@property (nonatomic, assign)NSInteger defaultMonth;@property (nonatomic, assign)NSInteger defaultDay;//显示的最低年@property (nonatomic, assign)NSInteger minShowYear;@property (nonatomic, assign)NSInteger yearSum;-(void)setDefaultTSelectYear:(NSInteger)defaultSelectYear defaultSelectMonth:(NSInteger)defaultSelectMonth defaultSelectDay:(NSInteger)defaultSelectDay;@endNS_ASSUME_NONNULL_END

#import "DatePickerView.h"@implementation DatePickerView- (void)initPickView {[super initPickView];//设置数据_minShowYear = 1940;//最小年份NSCalendar *calendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];// 获取当前日期NSDate* date = [NSDate date];// 指定获取指定年、月、日、时、分、秒的信息unsigned unitFlags = NSCalendarUnitYear |NSCalendarUnitMonth | NSCalendarUnitDay |NSCalendarUnitHour | NSCalendarUnitMinute |NSCalendarUnitSecond | NSCalendarUnitWeekday;// 获取不同时间字段的信息NSDateComponents* comp = [calendar components:unitFlags fromDate:date];_yearSum = comp.year-_minShowYear+1;_currentYear = comp.year;_currentMonth = comp.month;_currentDay = comp.day;_selectYear = comp.year;_selectMonth = comp.month;_selectDay = comp.day;_defaultYear = comp.year;_defaultMonth = comp.month;_defaultDay = comp.day;[self.pickerView setDelegate:self];[self.pickerView setDataSource:self];}- (void)setDefaultTSelectYear:(NSInteger)defaultSelectYear defaultSelectMonth:(NSInteger)defaultSelectMonth defaultSelectDay:(NSInteger)defaultSelectDay {if (defaultSelectYear != 0) {_defaultYear=defaultSelectYear;}if (defaultSelectMonth != 0) {_defaultMonth = defaultSelectMonth;}if (defaultSelectDay != 0) {_defaultDay=defaultSelectDay;}if (defaultSelectYear == -1) {_defaultYear=_currentYear+1;_defaultMonth=1;_defaultDay=1;}[self.pickerView selectRow:(_defaultYear - _minShowYear) inComponent:0 animated:NO];[self.pickerView selectRow:(_defaultMonth - 1) inComponent:1 animated:NO];[self.pickerView reloadComponent:1];[self.pickerView selectRow:(_defaultDay-1) inComponent:2 animated:NO];[self.pickerView reloadComponent:2];[self refreshPickViewData];}//返回列数- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {return 3;}- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {//每一行的高度return 40;}//返回行数- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {if (component == 0) {return self.yearSum;} else if(component == 1) {NSInteger yearSelected = [pickerView selectedRowInComponent:0] + self.minShowYear;return 12;} else {NSInteger yearSelected = [pickerView selectedRowInComponent:0] + self.minShowYear;NSInteger monthSelected = [pickerView selectedRowInComponent:1] + 1;return [self getDaysWithYear:yearSelected month:monthSelected];}}- (NSInteger)getDaysWithYear:(NSInteger)year month:(NSInteger)month {switch (month) {case 1:return 31;break;case 2://分为闰年和平年if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {return 29;}else{return 28;}break;case 3:return 31;break;case 4:return 30;break;case 5:return 31;break;case 6:return 30;break;case 7:return 31;break;case 8:return 31;break;case 9:return 30;break;case 10:return 31;break;case 11:return 30;break;case 12:return 31;break;default:return 0;break;}}- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {NSInteger selectYear;NSInteger selectMonth;switch (component) {case 0:[pickerView reloadComponent:1];selectYear = row + _minShowYear;[pickerView reloadComponent:2];break;case 1:selectMonth = row + 1;[pickerView reloadComponent:2];default:break;}[self refreshPickViewData];}//更新数据- (void)refreshPickViewData {self.selectYear = [self.pickerView selectedRowInComponent:0] + self.minShowYear;self.selectMonth = [self.pickerView selectedRowInComponent:1] + 1;self.selectDay = [self.pickerView selectedRowInComponent:2] + 1;}- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view {NSString *text;if (component == 0) {text = [NSString stringWithFormat:@"%zd年", row + _minShowYear];} else if (component == 1) {text = [NSString stringWithFormat:@"%zd月", row + 1];} else {text = [NSString stringWithFormat:@"%zd日", row + 1];}UILabel *label = [[UILabel alloc]init];label.textAlignment = 1;label.font = [UIFont systemFontOfSize:16];label.text = text;return label;}- (void)clickConfirmButton {if ([self.delegate respondsToSelector:@selector(pickerDateView:selectYear:selectMonth:selectDay:)]) {[self.delegate pickerDateView:self selectYear:self.selectYear selectMonth:self.selectMonth selectDay:self.selectDay];}//为了保留dismiss操作[super clickConfirmButton];}@end

//viewController.m#import <UIKit/UIKit.h>#import "DatePickerView.h"@interface ViewController : UIViewController<DatePickerViewDelegate>@end

//viewController.h#import "ViewController.h"@interface ViewController () {UIButton* dateButton;}@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.dateButton = [UIButton buttonWithType:UIButtonTypeCustom];dateButton.frame = CGRectMake(50, 100, 200, 50);[dateButton setTitle:@"选择日期" forState:UIControlStateNormal];[self.view addSubview:dateButton];[dateButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];[dateButton addTarget:self action:@selector(pickViewSelect) forControlEvents:UIControlEventTouchUpInside];}- (void)pickViewSelect {DatePickerView* datePickerView = [[DatePickerView alloc] init];datePickerView.delegate = self;[datePickerView setDefaultTSelectYear:2001 defaultSelectMonth:3 defaultSelectDay:23];[datePickerView show];}- (void)pickerDateView:(BasePickerView *)pickerDateView selectYear:(NSInteger)year selectMonth:(NSInteger)month selectDay:(NSInteger)day {NSString* string = [NSString stringWithFormat:@"%ld年%ld月%ld日", year, month, day];[dateButton setTitle:string forState:UIControlStateNormal];}@end

效果:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。