美文网首页iOS接下来要研究的知识点
iOS开发类携程日历,价格日历,单选,多选,可选不可选

iOS开发类携程日历,价格日历,单选,多选,可选不可选

作者: 何年何月 | 来源:发表于2018-09-04 16:49 被阅读101次

之前开发也遇到过酒店,火车票日历,我用了一款第三方软件,前期还行,随着后期功能(业务)增多,就不好使了,特别是那个循环架构,年 月 日这种的,修改起来特别麻烦。
新增业务例如:
1、价格日历,景点价格日历,机票价格日历
2、基地日历,我们基地价格分批次的 1-8天 110元/天,9-20天100 ,21-30天90,这就要求选择开始日期后,重新刷新数据,只能选择天数区域内的时间。
3、活动日历,活动不是每天搞,隔三差五的,一句话就是可点不可点,传日期输入,处理后展示出来。

先上图。 日历.gif
#define MSS_SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
#define MSS_SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
#define MSS_UTILS_COLORRGB(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]
#define MSS_Iphone6Scale(x) ((x) * MSS_SCREEN_WIDTH / 375.0f)
#define MSS_ONE_PIXEL (1.0f / [[UIScreen mainScreen] scale])

/*定义属性*/

// 选择点击颜色
#define SelectedColor [UIColor cyanColor]
// 被选中间颜色
#define SelMiddleColor [UIColor greenColor]


// DateLabel默认文字颜色
#define MSS_TextColor [UIColor blackColor]
// DateLabel选中时的背景色
#define MSS_SelectBackgroundColor MSS_UTILS_COLORRGB(29, 154, 72)
// DateLabel选中后文字颜色
#define MSS_SelectTextColor [UIColor whiteColor]
// SubLabel文字颜色
#define MSS_SelectSubLabelTextColor MSS_UTILS_COLORRGB(29, 154, 180);
// SubLabel选中开始文字
#define MSS_SelectBeginText @"开始"
// SubLabel选中结束文字
#define MSS_SelectEndText @"结束"
// 节日颜色
#define MSS_HolidayTextColor [UIColor purpleColor]
// 周末颜色
#define MSS_WeekEndTextColor [UIColor redColor]
// 不可点击文字颜色
#define MSS_TouchUnableTextColor MSS_UTILS_COLORRGB(150, 150, 150)
// 周视图高度
#define MSS_WeekViewHeight 60
// headerView线颜色
#define MSS_HeaderViewLineColor [UIColor lightGrayColor]
// headerView文字颜色
#define MSS_HeaderViewTextColor [UIColor blackColor]
// headerView高度
#define MSS_HeaderViewHeight 50
// 弹出层文字颜色
#define MSS_CalendarPopViewTextColor [UIColor whiteColor]
// 弹出层背景颜色
#define MSS_CalendarPopViewBackgroundColor [UIColor blackColor]

typedef NS_ENUM(NSInteger, MSSCalendarViewControllerType)
{
    MSSCalendarViewControllerLastType = 0,// 只显示当前月之前
    MSSCalendarViewControllerMiddleType,// 前后各显示一半
    MSSCalendarViewControllerNextType// 只显示当前月之后
};

typedef NS_ENUM(NSInteger, MSSCalendarWithUserType)
{
    MSSCalendarHotelType = 0,  // 酒店   入住 --- 离店
    MSSCalendarTrainType,      // 火车票,飞机票,单选无价格
    MSSCalendarAplaceType,     // 基地   价格
    MSSCalendarSecnicType,     // 景点   价格
    MSSCalendarPlaneType,      // 机票
    MSSCalendarActivityType    // 活动,线路

};

可以自定义以上属性,什么颜色,类型什么的。

核心思路就在这块,简单明了,传的有一个参数limitMonth,显示几个月的数据,MSSCalendarViewControllerNextType就是今天以后, components.month -= 1;获取当前月份减一,不要问为什么减一,打隔断点看看就知道了,MSSCalendarViewControllerLastType这是今天以前的limitMonth月的日期。


- (NSArray *)getCalendarDataSoruceWithLimitMonth:(NSInteger)limitMonth type:(MSSCalendarViewControllerType)type
{
    NSMutableArray *resultArray = [[NSMutableArray alloc]init];
    
    NSDateComponents *components = [self dateToComponents:_todayDate];
    components.day = 1;
    if(type == MSSCalendarViewControllerNextType)
    {
        components.month -= 1;
    }
    else if(type == MSSCalendarViewControllerLastType)
    {
        components.month -= limitMonth;
    }
    else
    {
        components.month -= (limitMonth + 1) / 2;
    }
    NSInteger i = 0;
    for(i = 0;i < limitMonth;i++)
    {
        components.month++;
        MSSCalendarHeaderModel *headerItem = [[MSSCalendarHeaderModel alloc]init];
        NSDate *date = [self componentsToDate:components];
        [_dateFormatter setDateFormat: @"yyyy年MM月"];
        NSString *dateString = [_dateFormatter stringFromDate:date];
        headerItem.headerText = dateString;
        headerItem.calendarItemArray = [self getCalendarItemArrayWithDate:date section:i];   // section就是当月数据页面的位置
        [resultArray addObject:headerItem];
    }
    return resultArray;
}

一共limitMonth个月,从第一个月开始排序,整理数组。下面是每一个单独月的日期数据


// 得到每一天的数据源
- (NSArray *)getCalendarItemArrayWithDate:(NSDate *)date section:(NSInteger)section
{
    NSMutableArray *resultArray = [[NSMutableArray alloc]init];
    NSInteger tatalDay = [self numberOfDaysInCurrentMonth:date];  // 本月多少天
    NSInteger firstDay = [self startDayOfWeek:date];  // 本月第一天是周几
     // 0 星期日  1  星期一      6星期六
    
    NSDateComponents *components = [self dateToComponents:date];
    
    // 判断日历有多少列
    // 一共多少天 加 第一天是周几就可以算出本月cell的数量

    NSInteger tempDay = tatalDay + (firstDay - 1);
    NSInteger column = 0;
    if(tempDay % 7 == 0)
    {
        column = tempDay / 7;
    }else{
        column = tempDay / 7 + 1;
    }
    
    NSInteger i = 0;
    NSInteger j = 0;
    components.day = 0;
    for(i = 0;i < column;i++)
    {
        for(j = 0;j < 7;j++)
        {
            if(i == 0 && j < firstDay - 1)  // 本月第一天前的数据
            {
                MSSCalendarModel *calendarItem = [[MSSCalendarModel alloc]init];
                calendarItem.year = 0;
                calendarItem.month = 0;
                calendarItem.day = 0;
                calendarItem.chineseCalendar = @"";
                calendarItem.holiday = @"";
                calendarItem.week = -1;
                calendarItem.dateInterval = -1;
                [resultArray addObject:calendarItem];
                continue;
            }
            components.day += 1;
            if(components.day == tatalDay + 1) // 本月数据循环结束
            {
                i = column;// 结束外层循环
                break;
            }
            MSSCalendarModel *calendarItem = [[MSSCalendarModel alloc]init];
            calendarItem.year = components.year;
            calendarItem.month = components.month;
            calendarItem.day = components.day;
            calendarItem.week = j;
            NSDate *date = [self componentsToDate:components];
            // 时间戳
            calendarItem.dateInterval = [self dateToInterval:date];
            if(_startDate == calendarItem.dateInterval)
            {
                _startIndexPath = [NSIndexPath indexPathForRow:0 inSection:section];
            }
            [self setChineseCalendarAndHolidayWithDate:components date:date calendarItem:calendarItem];
            
            [resultArray addObject:calendarItem];
        }
    }
    return resultArray;
}

价格日历这块,无非就是处理数据的时候加上了priceArray
@[ @{@"date":@"2018-09-08",@"price":@"238"}]


- (NSArray *)getJYCCalendarDataSoruceWithLimitMonth:(NSInteger)limitMonth type:(MSSCalendarViewControllerType)type calendarType:(MSSCalendarWithUserType)calendarType priceArray:(NSArray *_Nonnull)priceArray{
    
    NSMutableArray *resultArray = [[NSMutableArray alloc]init];
    NSMutableArray *priceMuArr = [NSMutableArray arrayWithArray:priceArray];
    
    NSDateComponents *components = [self dateToComponents:_todayDate];
    components.day = 1;
    if(type == MSSCalendarViewControllerNextType)
    {
        components.month -= 1;
    }
    else if(type == MSSCalendarViewControllerLastType)
    {
        components.month -= limitMonth;
    }
    else
    {
        components.month -= (limitMonth + 1) / 2;
    }
    NSInteger i = 0;
    for(i = 0;i < limitMonth;i++)
    {
        components.month++;
        MSSCalendarHeaderModel *headerItem = [[MSSCalendarHeaderModel alloc]init];
        NSDate *date = [self componentsToDate:components];
        [_dateFormatter setDateFormat: @"yyyy年MM月"];
        NSString *dateString = [_dateFormatter stringFromDate:date];
        headerItem.headerText = dateString;
        
        // 价格
        NSString *MMyue = [dateString substringWithRange:NSMakeRange(5, 2)];
        NSMutableArray *priArr = [NSMutableArray array];
        for (NSDictionary *dic in priceMuArr) {  // 从数据中选中当月的数据
            NSString *da = [dic objectForKey:@"date"];
            if (da.length > 7) {
                NSString *mm = [da substringWithRange:NSMakeRange(5, 2)];
                if (MMyue == mm) {
                    [priArr addObject:dic];
                }
            }
        }
        [priceMuArr removeObjectsInArray:priArr];  // 移除选中月份的数据
        
        
        
        headerItem.calendarItemArray = [self getCalendarItemArrayWithDate:date section:i calendarType:calendarType withPriceArray:priArr];
        [resultArray addObject:headerItem];   
        
        if (calendarType == MSSCalendarSecnicType || calendarType == MSSCalendarAplaceType || calendarType == MSSCalendarActivityType) {
            if (priceMuArr.count <= 0) {    // 如果价格数据数组为空时,不在展示以后的日历
                break;
            }
        }
    }
    return resultArray;
}

找到第一天数据的具体时间,然后依次把数组中的数据赋值给第一天后的每一天(必须保证时间日历的连续性)

        NSInteger priceTime = 0;
        if (priceArray.count > 0) {
            NSDictionary *dic = priceArray[0];
            NSString *ti = [dic objectForKey:@"date"];
            if (ti.length > 0) {
                priceTime = [self dateToInterval:[self dateFromString:ti]];
            }
        }

                // 时间戳
                NSInteger dateInterVal = [self dateToInterval:date];
                calendarItem.dateInterval = dateInterVal;
                if (priceTime == dateInterVal) {
                    indexB = 0;
                }
                if (indexB < priceArray.count) {
                    NSDictionary *dic = priceArray[indexB];
                    //                if (calendarType == MSSCalendarSecnicType) {
                    //                    calendarItem.price = [dic objectForKey:@"salePrice"];
                    //                }else if (calendarType == MSSCalendarAplaceType){
                    //                    calendarItem.userPrice = [dic objectForKey:@"userprice"];
                    //                    calendarItem.price = [dic objectForKey:@"webprice"];
                    //                }
                    calendarItem.price = [dic objectForKey:@"price"];
                    calendarItem.userInteractionEnabled = YES;
                }
                indexB++;

基地日历:选择一个开始时间后,后台刷新日历数据,把最小时间以前和最大时间以后的数据全部设置为不可选 userInteractionEnabled = NO;

- (NSArray *)getCalendarDataSoruceWithMinNum:(NSInteger )minNum MaxNum:(NSInteger )maxNum startDate:(NSInteger )startDate endDate:(NSInteger )endDate andDataArray:(NSArray *)dataArray{
    
    NSMutableArray *daArr = [NSMutableArray array];
    [daArr addObjectsFromArray:dataArray];
    if (startDate > 0) {
        for (int i = 0; i < dataArray.count; i++) {
            MSSCalendarHeaderModel *headerItem = daArr[i];
            for (int j = 0; j < headerItem.calendarItemArray.count; j++) {
                
                MSSCalendarModel *model = headerItem.calendarItemArray[j];
                
                if (model.dateInterval == startDate) {
                    
                }
                if(model.dateInterval >= startDate + minNum*24*3600 && model.dateInterval <= startDate + maxNum*24*3600){
                    model.middleSelect = YES;
                    model.userInteractionEnabled = YES;
                    
                }else{
                    model.userInteractionEnabled = NO;
                }
            }
        }
    }

    if (endDate > 0  || startDate == 0) {
        for (int i = 0; i < dataArray.count; i++) {
            MSSCalendarHeaderModel *headerItem = daArr[i];
            for (int j = 0; j < headerItem.calendarItemArray.count; j++) {
                
                MSSCalendarModel *model = headerItem.calendarItemArray[j];
                if ([model.price floatValue] > 0) {
                    model.userInteractionEnabled = YES;
                    model.middleSelect = NO;
                }
            }
        }
    }
    
    return daArr;
    
}

详见代码,
代码参考了一位大神,自己也封装了业务需求。
GitHub项目地址

相关文章

  • iOS开发类携程日历,价格日历,单选,多选,可选不可选

    之前开发也遇到过酒店,火车票日历,我用了一款第三方软件,前期还行,随着后期功能(业务)增多,就不好使了,特别是那个...

  • Mac开发环境搭建

    基础环境 安装mac 开发工具 安装 Homebrew iOS开发环境(可选) rvm 安装(可选) 安装rvm ...

  • 仿携程日历控件

    仿携程日历控件 RecycleView实现日历列表,其中每个itemView纯cavas绘制。 github地址 ...

  • Android日历选择按月分组并用recyclerview展示

    今天分享一个日历选择控件,可以定义日期可选、选择范围、按月分组展示。这个日历无非就是把每个日期的数据通过系统的日历...

  • iOS价格日历

    最近在做一个旅游相关的项目,用户在选择出游日期的时候,每天的价格不一样,所有需要开发一个价格日历的组件。就是在原有...

  • 工作总结

    这一周基本完成教师端古诗的开发模块:处理了活动统计页抽出学生列表cell为可选类型,type传值;古诗打卡页面日历...

  • iOS开发日历

    由于工作需求自己写了一个日历, 大概思路是: 通过collectionView来做, 具备上一月下一月的切换, 日...

  • NSCalendar相关

    ######先说下需求:选择日期弹出日历(跟途牛,携程等差不多就行。。。行) 初识NSCalendar到写完日历的...

  • iOS日历、NSCalendar初探(基础篇)。

    ######先说下需求:选择日期弹出日历(跟途牛,携程等差不多就行。。。行) 初识NSCalendar到写完日历的...

  • wrs-calendar日历插件

    前言 wrs-calendar是app原生日历控件插件 功能 支持单选、多选、单个范围选择日期 自定义选中日期颜色...

网友评论

    本文标题:iOS开发类携程日历,价格日历,单选,多选,可选不可选

    本文链接:https://www.haomeiwen.com/subject/glggwftx.html