iOS-自定義起始時間選擇器視圖


概述

自定義起始時間選擇器視圖, 調起時間選擇器, 傳值(起始時間/截止時間), 兩者時間均要合理, 不能超過未來時間, 並且起始時間不能大於截止時間. 點擊取消或空白處收起時間選擇器.

詳細

隨着界面的整體效果的各種展現, 起始時間選擇器的展現也需求突出!

最近項目中發現時間選擇器使用處還挺多, 數了數原型圖發現有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: 進行上傳時間段
}

三、壓縮文件截圖及運行效果

  1. 壓縮文件截圖:F17EC04A-4787-45D0-BA94-A61A85A73E25.png

2. 項目截圖

C3DFB9C1-207F-46A1-8BD7-75F35C74591F.png

3.運行效果:

時間選擇器.gif

 

4.效果截圖:

截圖.png

四、其他補充

界面性問題可以根據自己項目需求調整即可, 具體可參考代碼, 項目能夠直接運行!

 

注:本文著作權歸作者,由demo大師發表,拒絕轉載,轉載需要作者授權


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM