The simple implementation process of the IOS custom Calendar control _ios

Source: Internet
Author: User

Because the program requires a calendar control to be inserted, the requirement for that space is the calendar from the beginning of the day and the next six months. Access to the Internet basically said that as long as the acquisition of two conditions (the month of the first day of the week and how many days a month) you can implement a simple calendar, the rest on their own simple logic on the OK, Start the whole process from start to finish below

1. First do NSDate class, expand some methods to make conversion between dates more convenient

#import <Foundation/Foundation.h>

@interface nsdate (lywcalendar)

#pragma mark-Get Day
-(Nsinteger) Day: (NSDate *) date;
#pragma mark-Get month
-(Nsinteger) Month: (NSDate *) date;
#pragma mark-
(Nsinteger) Year: (NSDate *) date;
#pragma mark-Get the first day of the month
-(Nsinteger) Firstweekdayinthismonth: (NSDate *) date;
#pragma mark-Get how many days of the current month
-(Nsinteger) Totaldaysinmonth: (NSDate *) date;

@end

The following one by one implements these methods

#import "Nsdate+lywcalendar.h" @implementation nsdate (Lywcalendar)/** * Implementation part/#pragma mark--Get day-(Nsinteger) days :(nsdate *) date{nsdatecomponents *components = [[Nscalendar Currentcalendar] Components: (Nscalendarunityear | Nscalendarunitmonth |
 Nscalendarunitday) fromdate:date];
return components.day; #pragma mark--Get month-(nsinteger) Month: (NSDate *) date{nsdatecomponents *components = [[Nscalendar Currentcalendar] Co Mponents: (Nscalendarunityear | Nscalendarunitmonth |
 Nscalendarunitday) fromdate:date];
return components.month; #pragma mark--year of acquisition-(Nsinteger): (NSDate *) date{nsdatecomponents *components = [[Nscalendar Currentcalendar] com Ponents: (Nscalendarunityear | Nscalendarunitmonth |
 Nscalendarunitday) fromdate:date];
return components.year; #pragma mark-Get the first day of the current month of the week-(Nsinteger) Firstweekdayinthismonth: (NSDate *) date{Nscalendar *calendar = [Nscalendar C
 Urrentcalendar]; Set the first day of the week starting with the week, default 1, starting in Sunday [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];
 [Comp Setday:1];
 NSDate *firstdayofmonthdate = [Calendar Datefromcomponents:comp]; Nsuinteger firstweekday = [Calendar ordinalityofunit:nscalendarunitweekday inunit:nscalendarunitweekofmonth forDate:
 Firstdayofmonthdate];
If the setting starts from Sunday to calculate then needs to reduce one, if starts from Monday calculates then does not need to reduce the return firstWeekday-1; #pragma mark--How many days are there in the current month-(Nsinteger) Totaldaysinmonth: (NSDate *) date{nsrange daysinlastmonth = [[Nscalendar curren
 Tcalendar] Rangeofunit:nscalendarunitday inunit:nscalendarunitmonth fordate:date];
return daysinlastmonth.length;

 }

Next to write the logical part, in the Viewcontroller inside realization, first say thought, the first thought is to use CollectionView, but each month days are different in the calendar display is not the same, sometimes there are five elements sometimes there are six lines, Since you have to take this into account with AutoFill, here's the code implementation

#import "ViewController.h"
#import "Macro.h"
#import "nsdate+lywcalendar.h"
#import " LYWCollectionViewCell.h "
#import" LYWCollectionReusableView.h "

Define some global variables

static NSString *cellid = @ "Cellid";
static NSString *headerid = @ "Headerid";
static NSString *footerid = @ "Footerid";

@implementation Viewcontroller
{
 //Automatic layout
 uicollectionviewflowlayout *_layout;
 Table View
 Uicollectionview *_collectionview;
 The first day of the month a few
 Nsinteger firstdayinmounthinweekly;
 Nsmutablearray *_firstmounth;
 An array that holds six arrays
 Nsmutablearray *_sixarray;
 


//define week view, if for weekends the font color is green self.automaticallyadjustsscrollviewinsets = no;//Turn off automatic adaptation Nsarray
 *weektitlearray = @[@ "Sunday", @ "Monday", @ "Tuesday", @ "Wednesday", @ "Thursday", @ "Friday", @ "Saturday"]; for (int i = 0; i < Weektitlearray.count i++) {Uilabel *weektitlelable = [[Uilabel Alloc]initwithframe:cgrectmake (i
 * ((screenwidth/(Weektitlearray.count)), screenwidth/(Weektitlearray.count), 30)];
 if (i = = 0 | | | = = 6) {Weektitlelable.textcolor = [uicolor Greencolor];
 }else{Weektitlelable.textcolor = [Uicolor blackcolor];
 } weektitlelable.text = [Weektitlearray objectatindex:i];
 Weektitlelable.textalignment = Nstextalignmentcenter;
[Self.view addsubview:weektitlelable]; }
Set CollectionView and automatic layout, agent method is particularly important _layout = [[Uicollectionviewflowlayout alloc]init];
 The head is always at the top _layout.sectionheaderspintovisiblebounds = YES;
 Head View Height _layout.headerreferencesize = cgsizemake (414, 40);
 _layout.minimumlinespacing = 0;
 _layout.minimuminteritemspacing = 0; _collectionview = [[Uicollectionview alloc]initwithframe:cgrectmake (0, +, screenwidth, screenheight-64-30) Colle
 Ctionviewlayout:_layout];
 _collectionview.backgroundcolor = [Uicolor Whitecolor];
 Registration Form [_collectionview Registerclass:[lywcollectionviewcell class] forcellwithreuseidentifier:cellid]; Register Header View [_collectionview Registerclass:[lywcollectionreusableview class] Forsupplementaryviewofkind:
 Uicollectionelementkindsectionheader Withreuseidentifier:headerid];
   Register tail view//[_collectionview Registerclass:[uicollectionreusableview class] forcellwithreuseidentifier:footerid];
 _collectionview.delegate = self;
 _collectionview.datasource = self; [Self.view Addsubview:_collectionview];

Logical part, here's a long three-item expression.

(Daysinmounth > && (firstdayinthismounth = 6 | | firstdayinthismounth ==5)? 42:35)

Is whether the calendar is six lines or seven lines, which is based on the characteristics of the calendar, if the month is greater than 29 days, and the first day of the month of Saturday (in accordance with the guidelines of this program) or Sunday is returned six rows the remaining return three rows, it is possible to return four rows, But it's impossible for this procedure, and there's no need to make judgments.

 Numbermounthes is a macro definition that indicates the number of months to display, and the program requires six months, so the macro is defined as six//#define NUMBERMOUNTHES 6////create six arrays and assemble the six numbers into a large array _sixarr
 ay = [[Nsmutablearray alloc]init];
 for (int i = 0; i < numbermounthes i++) {Nsmutablearray *array = [[Nsmutablearray alloc]init];
 [_sixarray Addobject:array]; Write monthly calendar information for six arrays for (int i = 0; i < numbermounthes i++) {//get month int mounth = (int) [CurrentDate Month:curren
 Tdate] + i)%12;
 Nsdatecomponents *components = [[Nsdatecomponents alloc]init];
 Get the date of the next month, and convert it to date components.month = Mounth;
 Components.year = 2016 + mounth/12;
 Components.day = 1;
 Nscalendar *calendar = [Nscalendar Currentcalendar];
 NSDate *nextdate = [Calendar datefromcomponents:components];
 Get the first day of the month of the week nsinteger firstdayinthismounth = [Nextdate firstweekdayinthismonth:nextdate];
 How many days of the month daysinthismounth nsinteger daysinthismounth = [Nextdate totaldaysinmonth:nextdate];
 NSString *string = [[NSString alloc]init]; for (int j = 0; J < (Daysinmounth > 29 && (Firstdayinthismounth = = 6 | | | firstdayinthismounth ==5)? 42:35);
  J + +) {if (J < Firstdayinthismounth | | | J > daysinthismounth + firstDayInThisMounth-1) {string = @ "";
  [[_sixarray objectatindex:i]addobject:string];
  }else{string = [NSString stringwithformat:@ '%ld ', J-firstdayinthismounth + 1];
  [[_sixarray objectatindex:i]addobject:string];

 }
 }
 }

Here is the Proxy method

Needless to say, the number of cell and section number is returned
-(Nsinteger) CollectionView: (Uicollectionview *) CollectionView Numberofitemsinsection: (Nsinteger) section{return
 [[_sixarray objectatindex:section] count];
}

-(Nsinteger) Numberofsectionsincollectionview: (Uicollectionview *) collectionview{return
 _sixarray.count;
}

Here is the custom cell, very simple customization
-(Uicollectionviewcell *) CollectionView: (Uicollectionview *) CollectionView Cellforitematindexpath: (Nsindexpath *) indexpath{
 Lywcollectionviewcell *cell = [CollectionView Dequeuereusablecellwithreuseidentifier:cellid Forindexpath:indexpath];
 UIView *blackgroundview = [[UIView alloc]initwithframe:cgrectmake (0, 0, Cell.frame.size.width, cell.frame.size.height )];
 Blackgroundview.backgroundcolor = [Uicolor yellowcolor];
 Cell.dateLable.text = [[_sixarray objectatindex:indexpath.section]objectatindex:indexpath.row];
 NSDate *date = [[NSDate alloc]init];
 Nsinteger day = [date day:date];
Set the clicked color
 cell.selectedbackgroundview = Blackgroundview;
 return cell;
}

Custom cell. h

#import <UIKit/UIKit.h>

@interface lywcollectionviewcell:uicollectionviewcell

@property (nonatomic, Strong) Uilabel *datelable;

-(Instancetype) initWithFrame: (CGRect) frame;

@end

. m

#import "LYWCollectionViewCell.h"

@implementation Lywcollectionviewcell

-(Instancetype) initWithFrame: ( CGRect) frame{
 if (self = = [Super Initwithframe:frame]) {
 _datelable = [[Uilabel alloc] initWithFrame: Self.bounds];
 [_datelable Settextalignment:nstextalignmentcenter];
 [_datelable Setfont:[uifont systemfontofsize:17]];
 _datelable.textcolor = [Uicolor blackcolor];
 [Self addsubview:_datelable];
 }
 return self;
}
@end

Then agent

Cell size and Spacing
-(cgsize) CollectionView: (Uicollectionview *) CollectionView layout: (Uicollectionviewlayout *) Collectionviewlayout Sizeforitematindexpath: (Nsindexpath *) indexpath{return
 cgsizemake (SCREENWIDTH/7, SCREENWIDTH/7);
}

-(Uiedgeinsets) CollectionView: (Uicollectionview *) CollectionView layout: (Uicollectionviewlayout *) Collectionviewlayout Insetforsectionatindex: (nsinteger) section{return
 uiedgeinsetsmake (0, 0, 0, 0);
}

Since there is a calendar, it is always shown which year, the previous registered header view, here only need to implement the following proxy method

CollectionView is a little different. The header view also has a separate class, and the same as the cell first custom Headcell, but also very simple customization

. h Files

#import <UIKit/UIKit.h>

@interface lywcollectionreusableview:uicollectionreusableview

@property ( Nonatomic,strong) Uilabel *datelable;

-(Instancetype) initWithFrame: (CGRect) frame;

@end

. m file

#import "LYWCollectionReusableView.h"

@implementation lywcollectionreusableview

-(instancetype) initWithFrame: (cgrect) frame{
 if (self = = [Super Initwithframe:frame]) {
 _datelable = [[Uilabel alloc] InitWithFrame:self.bounds];
 [_datelable Settextalignment:nstextalignmentleft];
 [_datelable Setfont:[uifont systemfontofsize:20]];
 _datelable.textcolor = [Uicolor blackcolor];
 [Self addsubview:_datelable];
 }
 return self;
}

@end

Then the proxy method, here also has a three judgment, and the same as above, mainly to prevent December display as 0月

-(Uicollectionreusableview *) CollectionView: (Uicollectionview *) CollectionView Viewforsupplementaryelementofkind :(NSString *) kind Atindexpath: (Nsindexpath *) indexpath{
 if (kind = uicollectionelementkindsectionheader) {
 Lywcollectionreusableview *HEADERRV = [CollectionView dequeuereusablesupplementaryviewofkind:kind Withreuseidentifier:headerid Forindexpath:indexpath];
 Custom Blue
 headerrv.backgroundcolor = dodger_blue;
 NSDate *currentdate = [[NSDate alloc]init];
 Nsinteger year = ([currentdate month:currentdate] + indexpath.section)/12 + 2016;
 Nsinteger Mounth = ([currentdate month:currentdate] + indexpath.section)% 12 = 0? ([currentdate month:currentdate] + indexpath.section)%12;
 HeaderRV.dateLable.text = [NSString stringwithformat:@ "%ld years%ld months", year,mounth];
 return HEADERRV;
 } else{return
 nil
 }
}

Or agent, handle the check effect, select Yellow

-(void) CollectionView: (Uicollectionview *) CollectionView Didselectitematindexpath: (Nsindexpath *) indexPath{

 Lywcollectionviewcell *cell = [self Collectionview:_collectionview cellforitematindexpath:indexpath];

 NSDate *currentdate = [[NSDate alloc]init]; Prints the current date if (![ Cell.dateLable.text isequaltostring:@ ""]) {Nsinteger year = ([currentdate month:currentdate] + indexpath.section)/12 +

 2016;

 Nsinteger Mounth = ([currentdate month:currentdate] + indexpath.section)%12;

 Nsinteger day = [Cell.dateLable.text intvalue];

 NSLog (@ "%ld years%02ld month%02ld Day", Year,mounth,day); //Exclude null cell//Get month Nsinteger Mounth = ([currentdate month:currentdate] + indexpath.section)% 12 = 0?

 ([currentdate month:currentdate] + indexpath.section)%12;

 Nsdatecomponents *components = [[Nsdatecomponents alloc]init];

 Components.month = Mounth;

 Components.year = 2016 + mounth/12;

 Components.day = 1;

 Nscalendar *calendar = [Nscalendar Currentcalendar]; NSDate *nextdate = [Calendar daTefromcomponents:components];

 Get the first day of the month of the week nsinteger firstdayinthismounth = [Nextdate firstweekdayinthismonth:nextdate];

 How many days of the month daysinthismounth nsinteger daysinthismounth = [Nextdate totaldaysinmonth:nextdate]; if ((Indexpath.row < Firstdayinthismounth | | | indexpath.row > daysinthismounth + firstDayInThisMounth-1)) {//if clicked

 Blank table then click invalid [CollectionView cellforitematindexpath:indexpath].userinteractionenabled = NO;

 [CollectionView Reloaddata];

 }

}

Finally show the bad effect:

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.