概述
詳細
隨着界面的整體效果的各種展現, 起始時間選擇器的展現也需求突出!
最近項目中發現時間選擇器使用處還挺多, 數了數原型圖發現有6處. 便決定自定義時間選擇器視圖寫個 Demo, 封裝好在所需控制器里直接調用!
一、實現功能及主要思路
實現功能:
自定義起始時間選擇器視圖, 調起時間選擇器, 傳值(起始時間/截止時間), 兩者時間均要合理, 不能超過未來時間, 並且起始時間不能大於截止時間. 點擊取消或空白處收起時間選擇器.
其中兩者時間(起始時間/截止時間)是可以做限制,例如:當月月初1日 到 當天時間.
主要思路:
-
1. 創建時間選擇器Picker 且確認取消按鈕實現功能邏輯
-
2. 創建展示時間菜單的按鈕視圖 (按鈕: 圖片在右,標題在左的按鈕)
-
3. 創建時間選擇器視圖 且 起始時間/截止時間邏輯判斷
-
4. 使用代理傳值起始時間/截止時間(時間串轉換)
二、程序實現
第一步. 創建時間選擇器Picker 且確認取消按鈕實現功能邏輯
自定義ZLDatePickerView 文件:
@property (nonatomic, assign) id<ZLDatePickerViewDelegate> deleagte; // 最初/小時間(一般為左邊值) @property (nonatomic, strong) NSDate *minimumDate; // 截止時間(一般為右邊值) @property (nonatomic, strong) NSDate *maximumDate; // 當前選擇時間 @property (nonatomic, strong) NSDate *date; + (instancetype)datePickerView; - (void)showFrom:(UIView *)view;
使用代理傳值:
@protocol ZLDatePickerViewDelegate <NSObject> - (void)datePickerView:(ZLDatePickerView *)pickerView backTimeString:(NSString *)string To:(UIView *)view; @end
使用 xib 展現datePicker:
+ (instancetype)datePickerView { ZLDatePickerView *picker = [[NSBundle mainBundle] loadNibNamed:@"ZLDatePickerView" owner:nil options:nil].lastObject; picker.frame = CGRectMake(0, UI_View_Height - 250, UI_View_Width, 250); picker.maximumDate = [NSDate date]; return picker; } - (void)showFrom:(UIView *)view { UIView *bgView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; bgView.backgroundColor = [UIColor lightGrayColor]; bgView.alpha = 0.5; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)]; [bgView addGestureRecognizer:tap]; self.fromView = view; self.bgView = bgView; [[UIApplication sharedApplication].keyWindow addSubview:self.bgView]; [[UIApplication sharedApplication].keyWindow addSubview:self]; }
起始時間/截止時間設值:
- (void)setMinimumDate:(NSDate *)minimumDate { self.datePicker.minimumDate = minimumDate; } - (void)setMaximumDate:(NSDate *)maximumDate { self.datePicker.maximumDate = maximumDate; } - (void)setDate:(NSDate *)date { self.datePicker.date = date; }
確認/取消按鈕實現功能邏輯:
- (IBAction)cancel:(id)sender { [self dismiss]; } - (IBAction)makeSure:(id)sender { [self dismiss]; NSDate *date = self.datePicker.date; if ([self.deleagte respondsToSelector:@selector(datePickerView:backTimeString:To:)]) { [self.deleagte datePickerView:self backTimeString:[self fomatterDate:date] To:self.fromView]; } }
第二步. 創建展示時間菜單的按鈕視圖 (按鈕: 圖片在右,標題在左的按鈕)
這個可以根據需求來,有些不需要這個按鈕圖片在右邊的,則沒必要添加.
自定義ZLOppositeButton文件:
- (void)layoutSubviews { [super layoutSubviews]; CGFloat margin = 10; // 替換 title 和 image 的位置 // 圖片在右,標題在左 // 由於 button 內部的尺寸是自適應的.調整尺寸即可 CGFloat maxWidth = self.width - self.imageView.width - margin; if (self.titleLabel.width >= maxWidth) { self.titleLabel.width = maxWidth; } CGFloat totalWidth = self.titleLabel.width + self.imageView.width; self.titleLabel.x = (self.width - totalWidth - margin) * 0.5; self.imageView.x = CGRectGetMaxX(self.titleLabel.frame) + margin; }
接着利用上面的按鈕創建一個展示時間菜單的按鈕視圖ZLTimeBtn文件:
- (void)setup { self.backgroundColor = [UIColor clearColor]; [self setImage:[UIImage imageNamed:@"xiangxiadianji"] forState:UIControlStateNormal]; [self setTitle:[self timeStringDefault] forState:UIControlStateNormal]; [self setTitleColor:ZLColor(102, 102, 102) forState:UIControlStateNormal]; self.titleLabel.font = [UIFont systemFontOfSize:14]; } // 時間默認展示當天 - (NSString *)timeStringDefault { NSDate *date = [NSDate date]; return [date timeFormat:@"yyyy-MM-dd"]; }
其中我們上傳時間一般都是字符串而不是時間戳, 則需要進行轉換:
#import "NSDate+ZLDateTimeStr.h"
- (NSString *)timeFormat:(NSString *)dateFormat { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateStyle:NSDateFormatterMediumStyle]; [formatter setTimeStyle:NSDateFormatterShortStyle]; [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; [formatter setDateFormat:dateFormat]; return [formatter stringFromDate:self]; }
第三步. 創建時間選擇器視圖 且 起始時間/截止時間邏輯判斷
利用第二步自定義的按鈕來自定義ZLTimeView文件:
- (void)layoutSubviews { [super layoutSubviews]; self.beginTimeBtn.frame = CGRectMake(0, 0, self.width / 5.0 * 2, self.height); self.label.frame = CGRectMake(CGRectGetMaxX(self.beginTimeBtn.frame), 0, self.width / 5, self.height); self.endTimeBtn.frame = CGRectMake(CGRectGetMaxX(self.label.frame),0 , self.width / 5.0 * 2, self.height); self.line.frame = CGRectMake(0, self.height - 1, self.width, 1); }
- (void)setupSubview { // 起始時間按鈕 YYPTimeBtn *beginTimeBtn = [[YYPTimeBtn alloc] init]; beginTimeBtn.backgroundColor = [UIColor clearColor]; [beginTimeBtn addTarget:self action:@selector(beginTimeBtnClick:) forControlEvents:UIControlEventTouchUpInside]; // 起始時間默認展示當月一號 // [beginTimeBtn setTitle:[self timeStringDefaultWith:@"yyyy-MM-01"] forState:UIControlStateNormal]; [self addSubview:beginTimeBtn]; self.beginTimeBtn = beginTimeBtn; // 至label UILabel *label = [[UILabel alloc] init]; label.backgroundColor = [UIColor clearColor]; label.text = @"——"; label.textColor = YYPWhiteTitleColor; label.font = [UIFont systemFontOfSize:14]; label.textAlignment = NSTextAlignmentCenter; self.label = label; [self addSubview:label]; // 終止時間按鈕 YYPTimeBtn *endTimeBtn = [[YYPTimeBtn alloc] init]; [endTimeBtn addTarget:self action:@selector(endTimeBtnClick:) forControlEvents:UIControlEventTouchUpInside]; // 終止時間默認展示當天 // [endTimeBtn setTitle:[self timeStringDefaultWith:@"yyyy-MM-dd"] forState:UIControlStateNormal]; self.endTimeBtn = endTimeBtn; [self addSubview:endTimeBtn]; UIView *line = [[UIView alloc] init]; line.backgroundColor = YYPColor(204, 204, 204); self.line = line; [self addSubview:line]; }
這里強調一點: 如果默認展示的起始時間均為當天時間時,則在可在自定義按鈕里設置就好,不需添加下面方法.
// 自定義默認展示的當月起始時間 - (NSString *)timeStringDefaultWith:(NSString *)timeFormat { NSDate *date = [NSDate date]; return [date timeFormat:timeFormat]; }
使用代理:
@protocol ZLTimeViewDelegate <NSObject> /** * 時間選擇器視圖 * * @param beginTime 起始時間/開始時間 * @param endTime 終止時間按/結束時間 * */ - (void)timeView:(ZLTimeView *)timeView seletedDateBegin:(NSString *)beginTime end:(NSString *)endTime; @end
使用第一步創建的時間選擇器Picker, 來進行起始時間/截止時間邏輯判斷:
#pragma mark - ZLDatePickerViewDelegate - (void)beginTimeBtnClick:(UIButton *)btn { ZLDatePickerView *beginTimePV = [ZLDatePickerView datePickerView]; beginTimePV.date = [NSDate stringChangeTimeFormat:@"yyyy-MM-dd" string:btn.titleLabel.text]; if (self.maxDate) { beginTimePV.maximumDate = self.maxDate; } beginTimePV.deleagte = self; [beginTimePV showFrom:btn]; } - (void)endTimeBtnClick:(UIButton *)btn { ZLDatePickerView *endTimePV = [ZLDatePickerView datePickerView]; endTimePV.date = [NSDate stringChangeTimeFormat:@"yyyy-MM-dd" string:btn.titleLabel.text]; if (self.minDate) { endTimePV.minimumDate = self.minDate; } endTimePV.deleagte = self; [endTimePV showFrom:btn]; } - (void)datePickerView:(ZLDatePickerView *)pickerView backTimeString:(NSString *)string To:(UIView *)view { UIButton *btn = (UIButton *)view; if (btn == self.beginTimeBtn) { self.minDate = [NSDate stringChangeTimeFormat:@"yyyy-MM-dd" string:string]; } if (btn == self.endTimeBtn) { self.maxDate = [NSDate stringChangeTimeFormat:@"yyyy-MM-dd" string:string]; } [btn setTitle:string forState:UIControlStateNormal]; if ([self.delegate respondsToSelector:@selector(timeView:seletedDateBegin:end:)]) { [self.delegate timeView:self seletedDateBegin:self.beginTimeBtn.titleLabel.text end:self.endTimeBtn.titleLabel.text]; } }
第四步. 使用代理傳值起始時間/截止時間
在所需控制器里創建起始時間選擇器控件:
#import "ZLTimeView.h"
懶加載:
- (ZLTimeView *)timeView { if (!_timeView) { ZLTimeView *timeView = [[ZLTimeView alloc] initWithFrame:CGRectMake(0, 100, UI_View_Width, 50)]; timeView.backgroundColor = [UIColor greenColor]; timeView.delegate = self; _timeView = timeView; } return _timeView; }
創建添加起始時間選擇器控件:
[self.view addSubview:self.timeView];
使用代理<ZLTimeViewDelegate>:
#pragma mark - ZLTimeViewDelegate - (void)timeView:(ZLTimeView *)timeView seletedDateBegin:(NSString *)beginTime end:(NSString *)endTime { // TODO: 進行上傳時間段 }
三、壓縮文件截圖及運行效果
-
壓縮文件截圖:
2. 項目截圖
3.運行效果:
4.效果截圖:
四、其他補充
界面性問題可以根據自己項目需求調整即可, 具體可參考代碼, 項目能夠直接運行!