iOS 简约日历控件EBCalendarView的实现代码

时间:2021-11-04 08:44:50

本文介绍了ios 简约日历控件ebcalendarview的实现代码,分享给大家,具体如下:

ebcalendarview日历控件,调用简单,代码简洁。

github地址:https://github.com/woheduole/ebcalendarview

效果图

iOS 简约日历控件EBCalendarView的实现代码

调用示例

?
1
2
3
4
5
6
7
8
ebcalendarview *calendarview = [[ebcalendarview alloc] initwithframe:cgrectmake(0, 64, cgrectgetwidth(self.view.bounds), 0)];
  calendarview.delegate = self;
  //calendarview.maxlastmonths = 0;
  //calendarview.maxnextmonths = 0;
  [self.view addsubview:calendarview];
- (void)calendarview:(ebcalendarview*)calendarview didselecteddate:(nsdate*)date {
  nslog(@"选中日期:%@", [date stringwithformat:@"yyyy-mm-dd"]);
}

代码目录

iOS 简约日历控件EBCalendarView的实现代码

思路

ebcalendarview

?
1
2
3
4
5
6
7
_collectionview = [[uicollectionview alloc] initwithframe:cgrectzero collectionviewlayout:self.flowlayout];
    _collectionview.datasource = self;
    _collectionview.delegate = self;
    _collectionview.showsverticalscrollindicator = no;
    _collectionview.showshorizontalscrollindicator = no;
    _collectionview.backgroundcolor = [uicolor whitecolor];
    [_collectionview registerclass:[ebcalendardaycell class] forcellwithreuseidentifier:kebcalendarviewreuseidentifier];

 

复制代码 代码如下:
_flowlayout.itemsize = cgsizemake(viewwidth / kebcalendarviewcellcolumn, kebcalendarviewcellheight);

 

通过uicollectionview控件去显示日期数据,设置uicollectionviewflowlayout的itemsize,高度可以固定,宽度就是用视图的总宽度去除以7。

?
1
2
3
4
5
6
7
// 小数向上取整
  nsinteger rows = ceilf(_dates.count / kebcalendarviewcellcolumn);
  self.frame = ({
    cgrect frame = self.frame;
    frame.size.height = kebcalendarviewweekviewheight + kebcalendernavigationviewheight + (rows * kebcalendarviewcellheight);
    frame;
  });

切换月份的时候,由于每月的1号所在星期是不一致的,会导致行数不一样,比如一个月是31天,它的1号是星期日,这时候日期会有6行,如果它的1号是星期一,那么它会显示5行,这里会根据行数去动态的改变其高度。

?
1
2
3
4
5
6
- (nsdate *)datebyaddingmonths:(nsinteger)months {
  nscalendar *calendar = [nscalendar currentcalendar];
  nsdatecomponents *components = [[nsdatecomponents alloc] init];
  [components setmonth:months];
  return [calendar datebyaddingcomponents:components todate:self options:0];
}

月份在累加或累减的时候,通过nscalendar类直接增加月数,这样就不用自己去处理2018-12点击下个月切换到2019-01或者2019-01点击上个月切换到2018-12的操作了。

ebcalendarmodel 数据模型

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@property (nonatomic, assign) nsinteger year;
@property (nonatomic, assign) nsinteger month;
@property (nonatomic, assign) nsinteger day;
// 记录选中状态
@property (nonatomic, assign, getter=isselected) bool selected;
// 是否为当天
@property (nonatomic, assign, getter=istoday) bool today;
// 将year,month,day转换成nsdate
@property (nonatomic, strong, readonly) nsdate *date;
- (nsdate*)date {
  if (_year == 0 || _month == 0 || _day == 0) {
    return nil;
  }
  return [nsdate datewithstring:[nsstring stringwithformat:@"%zd-%zd-%zd"
              , _year
              , _month
              , _day] format:@"yyyy-mm-dd"];
}

ebcalenderweekview 周视图

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- (void)layoutsubviews {
  [super layoutsubviews];
  [self createweekview];
}
 
- (void)setweeks:(nsarray *)weeks {
  _weeks = weeks;
  [self createweekview];
}
 
- (void)createweekview {
  cgfloat viewwidth = cgrectgetwidth(self.bounds)
  , viewheight = cgrectgetheight(self.bounds);
  if (_weeks.count == 0 || viewheight == 0) return;
  [self.subviews makeobjectsperformselector:@selector(removefromsuperview)];
  nsinteger weekcount = _weeks.count;
  cgfloat weekwidth = viewwidth / weekcount;
  for (int n = 0; n < weekcount; n ++ ) {
    nsstring *week = _weeks[n];
    uilabel *weeklabel = [[uilabel alloc] initwithframe:cgrectmake(weekwidth * n, 0, weekwidth, viewheight)];
    weeklabel.font = [uifont systemfontofsize:14];
    weeklabel.textcolor = [uicolor colorwithhexstring:@"333333"];
    weeklabel.textalignment = nstextalignmentcenter;
    weeklabel.text = week;
    [self addsubview:weeklabel];
  }
}

根据传入的参数weeks动态添加uilabel显示周数据。

ebcalendernavigationview 月份导航视图

?
1
2
3
4
5
6
7
8
9
10
- (void)changemonthaction:(uibutton*)button {
  bool isnextmonth = no;
  if ([button isequal:_nextmonthbutton]) {
    // 下个月
    isnextmonth = yes;
  }
  if ([self.delegate respondstoselector:@selector(calendernavigationviewdidchangemonth:isnextmonth:)]) {
    [self.delegate calendernavigationviewdidchangemonth:self isnextmonth:isnextmonth];
  }
}

这里面主要就显示左右箭头和中间的年月显示,左右箭头是两个uibutton,在点击它们的时候通过代理把动作给传到ebcalendarview视图。

uicolor+ebadd 颜色辅助类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+ (uicolor *)colorwithhexstring:(nsstring *)hexstring {
  nsscanner *scanner = [nsscanner scannerwithstring:hexstring];
  unsigned hexnum;
  if (![scanner scanhexint:&hexnum]) return nil;
  return [uicolor colorwithrgbhex:hexnum];
}
 
+ (uicolor *)colorwithrgbhex:(uint32)hex {
  int r = (hex >> 16) & 0xff;
  int g = (hex >> 8) & 0xff;
  int b = (hex) & 0xff;
  
  return [uicolor colorwithred:r / 255.0f
              green:g / 255.0f
              blue:b / 255.0f
              alpha:1.0f];
}

代码中颜色都是用的16进制的颜色值,纯属个人习惯。

nsdate+ebadd 日期辅助类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 该方法来源自yykit
- (nsinteger)year;
 
// 该方法来源自yykit
- (nsinteger)month;
 
// 该方法来源自yykit
- (nsinteger)day;
 
// 该方法来源自yykit
- (nsinteger)weekday;
 
// 该方法来源自yykit
- (bool)istoday;
 
// 当前月有多少天
- (nsuinteger)numberofdaysinmonth;
 
// 该方法来源自yykit
- (nsstring *)stringwithformat:(nsstring *)format;
 
// 该方法来源自yykit
- (nsdate *)datebyaddingmonths:(nsinteger)months;
 
// 该方法来源自yykit
+ (nsdate *)datewithstring:(nsstring *)datestring format:(nsstring *)format;

小结:uicollectionview很强大的一个控件,通过uicollectionviewflowlayout去重写布局,可以实现很多酷炫的功能。这里的日历控件只是设置了item的宽高,属于很基础的使用。其中需要注意两点:1.每个月的1号是属于周几,然后去设置它的起始位置;2.每个月有多少天。app类型不一样也会导致日历控件实际呈现方式不一样,基本逻辑都一样,无非就是一些细微的控制。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://juejin.im/post/5af059b76fb9a07aa43c24a3