iOS仿滴滴预约用车时间选择器

栏目: IOS · 发布时间: 5年前

内容简介:前几天接到一个版本,里面包含了一个和滴滴预约用车选择时间的picker一样,需要选择当前时间的后面几天内的时间,包含了日期,小时和分钟数,分钟数的间隔是以10分钟为单位,如下图所示:当接到这个需求时,我的心里是有点小拒绝的,看着就是一个pickerView但是里面东西还是有的东西的,包含:个人认为,能自己做的尽量都少用三方库,减少对三方库的依赖,(PS:目前项目用了百度地图,iOS12删除了百度SDK用到的系统库,各种麻烦),所以决定自己造一个轮子。

前几天接到一个版本,里面包含了一个和滴滴预约用车选择时间的picker一样,需要选择当前时间的后面几天内的时间,包含了日期,小时和分钟数,分钟数的间隔是以10分钟为单位,如下图所示:

iOS仿滴滴预约用车时间选择器

当接到这个需求时,我的心里是有点小拒绝的,看着就是一个pickerView但是里面东西还是有的东西的,包含:

  1. 时间数据源获取,获取当前时间到3天后。
  2. 自定义时间数据源,分钟时间刻度单位为10分钟,不足10分钟的向上取整。
  3. 选择当天对当前小时数据和分钟数据的处理。
  4. 选择当前小时情况下对分钟数据源的处理。
  5. pickerView自定义展示(颜色,字体大小)

个人认为,能自己做的尽量都少用三方库,减少对三方库的依赖,(PS:目前项目用了百度地图,iOS12删除了百度SDK用到的系统库,各种麻烦),所以决定自己造一个轮子。

过程

获取天数

这里采用NSDate的 dateWithTimeIntervalSinceNow 函数再转成字符串,值得一提的是 NSDateFormatter ,根据官方文档的描述:

Creating a date formatter is not a cheap operation. If you are likely to use a formatter frequently, it is typically more efficient to cache a single instance than to create and dispose of multiple instances. One approach is to use a static variable.

创建一个formatter实例的代价是比较高,频繁使用时要考虑缓存,个人的做法是:

+ (void)load {
    if (!_dateFormatter) {
        _dateFormatter = [[NSDateFormatter alloc] init];
        [_dateFormatter setDateFormat:@"YYYY-MM-dd HH:mm"];
    }
}
复制代码

保证只创建一个NSDateFormatter实例,关于 +load 不做多说,想了解更多的可以看看之前的 Runtime源码 +load 和 +initialize

for (NSInteger i = 0; i < kDays; i++) {
        NSString *dateString = [self distanceDate:beginTime aDay:i];//获取第i天的日期
        NSString *week = [self currentWeek:dateString type:NO];//获取星期几     
}
复制代码

这里用到了

static NSInteger const kDays = 3;//从今天起能选择多少天 默认3天
复制代码

因为#define在编译的预处理阶段有一个宏替换操作,大量地使用#define会拖慢编译速度,而且宏没有类型,不做任何类型检查。Apple官方也是使用了更多的const。

分钟数向上取整

需求是当分钟数不为整10分钟时,向上取整,比如,16->20,41->50,所以对初始的数据源还有一步向上取整的操作:

NSString *beginTime = [self getTimerAfterCurrentTime:kBenginTimeDely];//开始时间(也就是当前时间20分钟后)
    NSInteger currentMin = [self getMString:beginTime];
    if (currentMin % kTimeInterval != 0) {
        beginTime = [self getTimerAfterTime:beginTime periodMin:(kTimeInterval - currentMin % kTimeInterval)];//开始时间向上取整
}
复制代码

这里把这三个数据抽取出来,提高灵活性,比如天数要5天之后or时间间隔要改成5分钟or最早时间是30分钟后这里只需要修改对应常量即可。

选中数据的处理

第一次的做法是在 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component 中切换日期或者小时的时候重新计算数据源,但是发现这样的效果并不好,有明显的卡顿现象,想起来这样的真的是很愚蠢的办法。应该初始化的时候计算好数据源,而不是每次都重新计算。

在切换日期或者小时数的时候切换数据源,具体实现:

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    if (component == 0) {
        return self.dataSourceModel.dateArray.count;
    } else if (component == 1) {
        if (self.selectedDateIndex == 0) {//选中的今天
            return self.dataSourceModel.todayHourArray.count;
        } else {
            return self.dataSourceModel.hourArray.count;
        }
    } else {
        if (self.selectedHourIndex == 0 && self.selectedDateIndex == 0) {//选中的当天的第一个小时
            return self.dataSourceModel.todayMinuteArray.count;
        } else {
            return self.dataSourceModel.minuteArray.count;
        }
    }
}
复制代码

关于数据源的计算,比较直观,这里就不贴出来了,详情请看 QFDatePickerViewQFTimerUtil 文件 + (QFTimerDataSourceModel *)configDataSource 方法

pickerView自定义展示

可以直接通过默认的代理方法 - (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component __TVOS_PROHIBITED 实现日期显示,但是这样的展示效果却和设计图差距较大,所以实现了 - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UILabel *)recycledLabel 自定义展示:

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UILabel *)recycledLabel {
    if (!recycledLabel) {
        recycledLabel = [[UILabel alloc] init];
    }
    recycledLabel.textAlignment = NSTextAlignmentCenter;
    [recycledLabel setFont:[UIFont systemFontOfSize:18]];
    recycledLabel.textColor = [UIColor colorWithRed:34.0f / 255.0f green:34.0f / 255.0f blue:34.0f / 255.0f alpha:1.0f];
    ...
   	recycledLabel.text = minModel.showMinuteString;
    return recycledLabel;
}
复制代码

使用方式

手动拖入文件夹 或者 pod 'QFDatePicker'
导入QFTimerPicker头文件,在对应的地方调用picker的初始化方法和show方法:

/**
 初始化时间选择

 @param block 回调block 参数即是选择的日期
 @return 时间选择器实例
 */
- (instancetype)initWithResponse:(ReturnBlock)block;

/**
 初始化时间选择
 
 @param superView 时间选择器的父View,若为空,将时间选择器加载在window上面
 @param block 回调block 参数即是选择的日期
 @return 时间选择器实例
 */
- (instancetype)initWithSuperView:(UIView *)superView response:(ReturnBlock)block;
复制代码

注释比较清楚了,通过 superView 参数,控制这个picker加载在什么视图上,当其为空的时候加载在window上。

选中的时间再block中回调(PS:这里如果把picker设置为属性时,考虑循环强引用的问题)

具体调用案例:

QFTimerPicker *picker = [[QFTimerPicker alloc]initWithSuperView:self.view response:^(NSString *selectedStr) {
        NSLog(@"%@",selectedStr);
        [sender setTitle:selectedStr forState:UIControlStateNormal];
    }];
[picker show];
复制代码

以上所述就是小编给大家介绍的《iOS仿滴滴预约用车时间选择器》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

设计沟通十器

设计沟通十器

Daniel M. Brown / 樊旺斌 / 机械工业出版社 / 2008-12 / 49.00元

本书提供了网站设计时所需的可交付文档资料包括:概念模型,站点地图,可用性报告等,这些文档资料是设计人员和客户进行交流的主要工具。本书深入讨论了文档推介和风险规避技巧,向你展示了如何将文档资料按要求制作成有效的交流工具。 本书内容全面,结构清晰,讲解详细。可作为网站设计人员的参考用书。 关于网站设计的多数讨论好像都着眼于流程的创建,然而,要想把概念变为现实,需要一整套强大的可交付文档资料......一起来看看 《设计沟通十器》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具