您的位置:首页 > 移动开发 > IOS开发

iOS-时间选择器

2015-12-09 00:00 495 查看
前言

项目开发中常会有时间选择的需求,但是苹果系统的时间选择控件交互逻辑不太友好,换句话说就是不能满足我们开发的需求,一般常用的是需要选择开始时间和结束时间进行数据筛选,因此这个自定义控件主要往这个方向的封装,但是大概思路应该是这样的。

一、设计的思路:采用分段控件区分当前选择的时间是开始时间还是结束时间,然后判断两个时间的合法性,最后再判断底部的“确定”按钮是否可点击;回调支持delegate与block回调,若两者都设置,会优先采用delegate回调。showTopSegmentedControl属性,用于控制是否显示顶部的segmentedControl控件,默认是显示的,加上该属性主要是满足有单个时间选择的需求。

#import <UIKit/UIKit.h>
@class DYLDatePickerView;

typedef NS_ENUM(NSInteger, DYLDateType) {
DYLDateTypeStartDate = 0,
DYLDateTypeEndDate
};

@protocol DYLDatePickerViewDelegate <NSObject>

@optional
- (void)callback:(DYLDatePickerView *)datePickerView beginDateStr:(NSString *)beginDateStr endDateStr:(NSString *)endDateStr;

@end

typedef void(^CallbackCompleteBlock)(NSString *beginDateStr, NSString *endDateStr);

@interface DYLDatePickerView : UIView

@property (assign, nonatomic) NSInteger maximumIntervalDay;

@property (strong, nonatomic) NSString *minLimitDate;

@property (assign, nonatomic) NSTimeInterval duration;

//是否显示顶部segmentedControl
@property (assign, nonatomic) BOOL showTopSegmentedControl;

@property (weak, nonatomic) id<DYLDatePickerViewDelegate> delegate;

@property (copy, nonatomic) CallbackCompleteBlock completeBlock;

- (void)show;

- (void)hide;

@end

#import "DYLDatePickerView.h"
#import "UIUtils.h"
#import <Masonry.h>
#import "DYLDatePickerManager.h"

#define mScreenWidth  ([UIScreen mainScreen].bounds.size.width)
#define mScreenHeight ([UIScreen mainScreen].bounds.size.height)
#define mEmptyStr @""

#define mBlueColor [UIColor colorWithRed:50.0/255.0 green:162.0/255.0 blue:248.0/255.0 alpha:1.0]
#define mGrayColor [UIColor colorWithRed:165/255.0 green:165/255.0 blue:165/255.0 alpha:1.0]

static CGFloat const DYLDatePickerAnimationDuration = 0.25;
static CGFloat const DYLDatePickerButtonHeight = 30;

@interface DYLDatePickerView ()

@property (strong, nonatomic) UIView *bgView;
@property (strong, nonatomic) UISegmentedControl *dateSegmentView;
@property (assign, nonatomic) DYLDateType dateType;

@property (strong, nonatomic) UIView *sureDateView;
@property (strong, nonatomic) UIButton *sureDateButton;
@property (strong, nonatomic) UILabel *tipLabel;

@property (strong, nonatomic) UIDatePicker *datePicker;

@property (strong, nonatomic) UIView *bottomView;
@property (strong, nonatomic) UIButton *completeRefreshButton;

@property (copy, nonatomic) NSString *beginDateStr;
@property (copy, nonatomic) NSString *endDateStr;

@end

@implementation DYLDatePickerView

#pragma mark - lifeCicle
- (instancetype)init
{
self = [super init];
if (self) {
self.frame = CGRectMake(0, mScreenHeight, mScreenWidth, 320);
self.backgroundColor = [UIColor whiteColor];

[self commonInit];
[self createBgView];
[self createDatePickerView];
[self configDatePickerView];
}
return self;
}

#pragma mark - Private Method
- (void)commonInit
{
self.duration = DYLDatePickerAnimationDuration;
self.showTopSegmentedControl = YES;
}

- (void)createBgView
{
self.bgView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.bgView.hidden = YES;
self.bgView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.3];

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)];
[self.bgView addGestureRecognizer:tapGesture];
}

- (void)createDatePickerView
{
self.dateSegmentView = [UIUtils segmentViewWithTintColor:mBlueColor items:@[@"开始时间", @"结束时间"]];
self.dateSegmentView.selectedSegmentIndex = 0;
[self.dateSegmentView addTarget:self action:@selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
[self addSubview:self.dateSegmentView];

self.sureDateView = [UIUtils viewWithBackgroudColor:[UIColor whiteColor]];
[self addSubview:self.sureDateView];

self.sureDateButton = [UIUtils buttonWithTitle:@"确定" titleColor:mBlueColor fontSize:15.f cornerRadius:0.f];
[self.sureDateButton addTarget:self action:@selector(sureDateButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[self.sureDateView addSubview:self.sureDateButton];

self.tipLabel = [UIUtils labelWithTextColor:mGrayColor textAlignment:NSTextAlignmentLeft text:@"开始选择时间" fontSize:14.f];
[self.sureDateView addSubview:self.tipLabel];

self.datePicker = [UIUtils datePickerWithLocale:@"zh-CN" datePickerMode:UIDatePickerModeDate];
[self addSubview:self.datePicker];

self.bottomView = [UIUtils viewWithBackgroudColor:[UIColor whiteColor]];
[self addSubview:self.bottomView];

self.completeRefreshButton = [UIUtils buttonWithBackgroundColor:mBlueColor titleColor:[UIColor whiteColor] selectedColor:[UIColor lightGrayColor] title:@"确定" fontSize:15.f cornerRadius:3.f];
self.completeRefreshButton.enabled = NO;
[self.completeRefreshButton addTarget:self action:@selector(callback) forControlEvents:UIControlEventTouchUpInside];
[self.bottomView addSubview:self.completeRefreshButton];
}

- (void)configDatePickerView
{
[self.dateSegmentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(@15);
make.width.equalTo(@200);
make.height.equalTo(@(DYLDatePickerButtonHeight));
make.centerX.equalTo(self);
}];

[self.sureDateView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.dateSegmentView.mas_bottom).offset(15);
make.left.and.right.equalTo(self);
make.height.equalTo(@40);
}];

[self.sureDateButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(@0);
make.right.equalTo(self.mas_right);
make.width.equalTo(@60);
make.bottom.equalTo(self.sureDateView.mas_bottom);
}];

[self.tipLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(@0);
make.left.equalTo(@15);
make.right.equalTo(self.sureDateButton.mas_left).offset(-15);
make.bottom.equalTo(self.sureDateView.mas_bottom);
}];

[self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(@60);
make.left.and.right.equalTo(self);
make.bottom.equalTo(self);
}];

[self.datePicker mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.sureDateView.mas_bottom).offset(15);
make.left.and.right.equalTo(self);
make.bottom.equalTo(self.bottomView.mas_top);
}];

[self.completeRefreshButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.mas_left).offset(50);
make.right.equalTo(self.mas_right).offset(-50);
make.height.mas_equalTo(35);
make.centerY.equalTo(self.bottomView.mas_centerY);
}];
}

- (void)setMinLimitDate:(NSString *)minLimitDate
{
_minLimitDate = minLimitDate;
self.datePicker.minimumDate = [[DYLDatePickerManager sharedManager].formatter dateFromString:minLimitDate];
}

- (void)setShowTopSegmentedControl:(BOOL)showTopSegmentedControl
{
_showTopSegmentedControl = showTopSegmentedControl;
if (showTopSegmentedControl && self.dateSegmentView.isHidden) {
self.dateSegmentView.hidden = !showTopSegmentedControl;
[self.sureDateView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.dateSegmentView.mas_bottom).offset(15);
make.left.and.right.equalTo(self);
make.height.equalTo(@40);
}];
} else {
if (!showTopSegmentedControl && !self.dateSegmentView.isHidden) {
self.dateSegmentView.hidden = !showTopSegmentedControl;
[self.sureDateView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.and.left.and.right.equalTo(self);
make.height.equalTo(@40);
}];
}
}
}

- (void)sureDateButtonClick:(UIButton *)sender
{
switch (_dateType) {
case DYLDateTypeStartDate: {
self.beginDateStr = [[DYLDatePickerManager sharedManager].formatter stringFromDate:self.datePicker.date];
break;
}
case DYLDateTypeEndDate: {
self.endDateStr = [[DYLDatePickerManager sharedManager].formatter stringFromDate:self.datePicker.date];
break;
}
default:
break;
}

[self refreshDatePickerView];
}

- (void)segmentAction:(UISegmentedControl *)sender
{
self.dateType = sender.selectedSegmentIndex;
switch (_dateType) {
case DYLDateTypeStartDate: {
if (_beginDateStr) {
[self.datePicker setDate:[[DYLDatePickerManager sharedManager].formatter dateFromString:_beginDateStr] animated:YES];
}
break;
}
case DYLDateTypeEndDate: {
if (_endDateStr) {
[self.datePicker setDate:[[DYLDatePickerManager sharedManager].formatter dateFromString:_endDateStr] animated:YES];
}
break;
}
default:
break;
}
}

- (void)refreshDatePickerView
{
NSString *beginDateStr = _beginDateStr ? _beginDateStr : mEmptyStr;
NSString *endDateStr = _endDateStr ? _endDateStr : mEmptyStr;

if (self.showTopSegmentedControl) {
self.tipLabel.text = [NSString stringWithFormat:@"%@,%@", beginDateStr, endDateStr];
self.completeRefreshButton.enabled = _beginDateStr && _endDateStr;
} else {
self.tipLabel.text = beginDateStr;
self.completeRefreshButton.enabled = _beginDateStr || _endDateStr;
}

if (self.completeRefreshButton.enabled) {
if (self.showTopSegmentedControl) {
NSInteger distanceDays = [[DYLDatePickerManager sharedManager] distanceFrom:_beginDateStr to:_endDateStr];
if (distanceDays > self.maximumIntervalDay) {
self.completeRefreshButton.enabled = NO;
[self.completeRefreshButton setTitle:@"超过规定时间间隔" forState:UIControlStateDisabled];
} else {
if (distanceDays < 0) {
self.completeRefreshButton.enabled = NO;
[self.completeRefreshButton setTitle:@"开始时间须小于结束时间" forState:UIControlStateDisabled];
} else {
[self.completeRefreshButton setTitle:@"确定" forState:UIControlStateNormal];
}
}
}
}
}

- (void)callback
{
if ([self.delegate respondsToSelector:@selector(callback:beginDateStr:endDateStr:)]) {
[self.delegate callback:self beginDateStr:self.beginDateStr endDateStr:self.endDateStr];
} else {
if (self.completeBlock) {
self.completeBlock(self.beginDateStr, self.endDateStr);
}
}
}

- (void)show
{
UIWindow *window = [UIApplication sharedApplication].keyWindow;
[window addSubview:self.bgView];
[window addSubview:self];
}

- (void)didMoveToWindow
{
if (self.window) {
[UIView animateWithDuration:self.duration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.bgView.hidden = NO;
CGRect newFrame = self.frame;
newFrame.origin.y = mScreenHeight - CGRectGetHeight(self.frame);
self.frame = newFrame;
} completion:^(BOOL finished) {
if (finished) {

}
}];
}
}

- (void)hide
{
[UIView animateWithDuration:self.duration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
CGRect newFrame = self.frame;
newFrame.origin.y = mScreenHeight;
self.frame = newFrame;
} completion:^(BOOL finished) {
if (finished) {
self.bgView.hidden = YES;
[self.bgView removeFromSuperview];
[self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self removeFromSuperview];
}
}];
}

@end


二、点击时间选择按钮,自下而上弹出控件。

#import "ViewController.h"
#import "DYLDatePickerView.h"

@interface ViewController () <DYLDatePickerViewDelegate>

@property (strong, nonatomic) UIButton *showDateButton;

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor  = [UIColor whiteColor];
self.showDateButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.showDateButton.frame = CGRectMake(20, 100, 240, 40);
[self.showDateButton setTitle:@"时间" forState:UIControlStateNormal];
[self.showDateButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.showDateButton addTarget:self action:@selector(handleAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.showDateButton];
}

- (void)handleAction:(UIButton *)sender
{
DYLDatePickerView *datePickerView = [[DYLDatePickerView alloc] init];
datePickerView.maximumIntervalDay = 90;
datePickerView.minLimitDate = @"2014-04-01";
datePickerView.delegate = self;

__weak typeof(self) weakSelf = self;
datePickerView.completeBlock = ^(NSString *beginDateStr, NSString *endDateStr) {
[weakSelf.showDateButton setTitle:[NSString stringWithFormat:@"%@-%@", beginDateStr, endDateStr] forState:UIControlStateNormal];
};
[datePickerView show];
}

// 优先执行delegate逻辑
- (void)callback:(DYLDatePickerView *)datePickerView beginDateStr:(NSString *)beginDateStr endDateStr:(NSString *)endDateStr
{
[self.showDateButton setTitle:[NSString stringWithFormat:@"%@-%@", beginDateStr, endDateStr] forState:UIControlStateNormal];
}

@end


三、最后

DYLDatePickerView中有几个工具类没有给出来,其实也不是很复杂的内容,仅仅封装了一些事件判断逻辑以及创建控件的帮助管理器,DYLDatePickerView的github下载地址。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  时间选择器