iOS自定义日历

作者: shihh999 | 来源:发表于2019-07-15 13:30 被阅读11次

工作记录,加深记忆,方便以后查询。

自定义日历从结构上来分,可以分为月和日。月可以用UITableView来实现,一个section,每个section只有一个cell作为一个月来显示。日是每个月的基本元素,可以用UICollectionView来实现。

首先分析月:这个很容易确定,只要基于当天来计算出当前月。然后以当前月为基础开始自增,可以计算出任意月在UITableView上的位置,属于第几个section。

分析日:上面已经说了,每个cell是一个月,那么也就是每一个cell就是一个UICollectionView,那么每一天就是UICollectionViewCell。这样就要知道每个月有多少天,每个月的第一天是星期几,每个月有几周。确定了这些基础数据,既能够确定出每个月的具体高度。

下面是提取这些数据的具体方法:

1、定义 MonthModel 和 DayModel

@interface MonthModel : NSObject

////年

@property (nonatomic, assign) NSUInteger year;

////月

@property (nonatomic, assign) NSUInteger month;

////一个月有多少天

@property (nonatomic, assign)NSUInteger days;

////每个月第一天是星期几

@property (nonatomic, assign) NSUInteger firstWeekDay;

////一周7天可以排几行

@property (nonatomic, assign) NSUInteger lineCount;

/////用一个月的任意一天初始化

- (instancetype)initWithDate:(NSDate*)inDate;

@end

@interface DayModel : NSObject

////年

@property (nonatomic, assign) NSInteger year;

////月

@property (nonatomic, assign) NSInteger month;

////日

@property (nonatomic, assign) NSInteger day;

////星期几

@property (nonatomic, strong) NSString* weakDay;

@end

2、 一个个获取初始化数据

+ (NSDateFormatter*)dataFormatter {

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

    [dateFormatter setDateFormat:@"yyyy-MM-dd"];

    [dateFormatter setLocale:[NSLocale currentLocale]];

    return dateFormatter;

}

////-- 获取年

+ (NSInteger)year:(NSString*)date {

    NSDateFormatter  *dateFormatter = [[self class] dataFormatter];

    NSDate          *startDate    = [dateFormatter dateFromString:date];

    NSDateComponents*components    = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:startDate];

    return components.year;

}

//// -- 获取月

+ (NSInteger)month:(NSString*)date {

    NSDateFormatter  *dateFormatter = [[selfclass] dataFormatter];

    NSDate          *startDate    = [dateFormatter dateFromString:date];

    NSDateComponents*components    = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:startDate];

    return components.month;

}

////-- 获取日

+ (NSInteger)day:(NSString*)date {

    NSDateFormatter  *dateFormatter = [[NSDate class] dataFormatter];

    NSDate          *startDate    = [dateFormatter dateFromString:date];

    NSDateComponents*components    = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:startDate];

    return components.day;

}

 /////-- 获得当前月份第一天星期几

+ (NSInteger)firstWeekdayInThisMonth:(NSDate*)date {

    NSCalendar *calendar = [NSCalendar currentCalendar];

    //设置每周的第一天从周几开始,默认为1,从周日开始

    [calendar setFirstWeekday:1];//1.Sun. 2.Mon. 3.Thes. 4.Wed. 5.Thur. 6.Fri. 7.Sat.

    NSDateComponents *comp = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date];

    [compsetDay:1];

    NSDate    *firstDayOfMonthDate = [calendar dateFromComponents:comp];

    NSUInteger firstWeekday        = [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonthDate];

    //若设置从周日开始算起则需要减一,若从周一开始算起则不需要减

    return firstWeekday -1;

}

/// 获取当前月有多少天

+ (NSInteger)totaldaysInMonth:(NSDate*)date {

    NSRange daysInLastMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date];

    return daysInLastMonth.length;

}

3、基础数据获取完,就是怎么在UI上展示

首先是最外层的月(比较简单的,这里获取这些数据主要是来确定,月cell的高度 和 从星期几开始显示):

- (void)setDate:(NSDate*)inDate

{

    NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:inDate];

    _year=  components.year;

    _month= components.month;

    _days = [NSDate totaldaysInMonth:inDate];

    _firstWeekDay = [NSDate firstWeekdayInThisMonth:inDate];

    _lineCount= [NSDatelineNum:inDate];

}

@end

再就是每个月的具体日的显示(这里用了一个小技巧,因为每个月的第一天不一定是周一, 所以用cell下表和第一天是周几做比较。>=0,则表示这个cell应该显示 ):

- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView cellForItemAtIndexPath:(NSIndexPath*)indexPath

{

    DayCollectionCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCollectionViewCellIdentifier forIndexPath:indexPath];

    NSIntegerday = indexPath.row-mMonth.firstWeekDay+1;

    [cellsetDay:(day<=mMonth.days? day:-1) withMonth:mMonth];

    returncell;

}

//////日期的显示

- (void)setDay:(NSInteger)inDay withMonth:(MonthModel*)inMonth

{

    [mDay setYear:inMonth.year];

    [mDay setMonth:inMonth.month];

    if(inDay >0)

    {///显示日期}

    else

    {

        [mDayLabel setText:@""];

        [mDesLabel setText:@""];

        [mDay setDay:-1];

        [mDayLabel setBackgroundColor:kAppBackgroundColor];

    }

}

/////

这篇文章只是把主要的思路和要用的方法写了一下,做个记录。

最主要的就是怎么计算month cell的高度,和每个月从周记开始显示day。

相关文章

网友评论

    本文标题:iOS自定义日历

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