欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-18 10:08:46
本文介绍了ios 简约日历控件ebcalendarview的实现代码,分享给大家,具体如下: ebcalendarview日历控件,调用简单,代码简洁。 githu...

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

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

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

效果图

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

调用示例

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

_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。

// 小数向上取整
  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行,这里会根据行数去动态的改变其高度。

- (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 数据模型

@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 周视图

- (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 月份导航视图

- (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 颜色辅助类

+ (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 日期辅助类

// 该方法来源自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类型不一样也会导致日历控件实际呈现方式不一样,基本逻辑都一样,无非就是一些细微的控制。

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

上一篇:

下一篇: