Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/johnvuko/JTCalendar

A customizable calendar view for iOS.
https://github.com/johnvuko/JTCalendar

calendar ios

Last synced: 3 months ago
JSON representation

A customizable calendar view for iOS.

Awesome Lists containing this project

README

        

# JTCalendar

[![CI Status](http://img.shields.io/travis/jonathantribouharet/JTCalendar.svg)](https://travis-ci.org/jonathantribouharet/JTCalendar)
![Version](https://img.shields.io/cocoapods/v/JTCalendar.svg)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
![License](https://img.shields.io/cocoapods/l/JTCalendar.svg)
![Platform](https://img.shields.io/cocoapods/p/JTCalendar.svg)

JTCalendar is an easily customizable calendar control for iOS.

## Installation

With [CocoaPods](http://cocoapods.org), add this line to your Podfile.

pod 'JTCalendar', '~> 2.0'

### Carthage

To use this project with [Carthage](https://github.com/Carthage/Carthage), add this line to your Cartfile.

github "jonathantribouharet/JTCalendar" ~> 2.2

## Screenshots

![Example](./Screens/example.gif "Example View")
![Example](./Screens/example.png "Example View")

### Warning

The part below the calendar in the 2nd screenshot is not provided.

## Features

- horizontal and vertical calendar
- highly customizable either by subclassing default class provided or by creating your own class implementing a protocol
- support internationalization
- week view mode
- limited range, you can define a start and an end to you calendar

## Usage

### Basic usage

You have to create two views in your `UIViewController`:

- The first view is `JTCalendarMenuView` and it represents the part with the months names. This view is optional.
- The second view is `JTHorizontalCalendarView` or `JTVerticalCalendarView`, it represents the calendar itself.

Your `UIViewController` have to implement `JTCalendarDelegate`, all methods are optional.

```objective-c
#import

#import

@interface ViewController : UIViewController

@property (weak, nonatomic) IBOutlet JTCalendarMenuView *calendarMenuView;
@property (weak, nonatomic) IBOutlet JTHorizontalCalendarView *calendarContentView;

@property (strong, nonatomic) JTCalendarManager *calendarManager;

@end
```

`JTCalendarManager` is used to coordinate `calendarMenuView` and `calendarContentView` and provide a default behavior.

```objective-c
@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];

_calendarManager = [JTCalendarManager new];
_calendarManager.delegate = self;

[_calendarManager setMenuView:_calendarMenuView];
[_calendarManager setContentView:_calendarContentView];
[_calendarManager setDate:[NSDate date]];
}

@end

```

The Example project contains some use cases you may check before asking questions.

### Advanced usage

Even if all methods of `JTCalendarManager` are optional you won't get far without implementing at least the two next methods:
- `calendar:prepareDayView:` this method is used to customize the design of the day view for a specific date. This method is called each time a new date is set in a dayView or each time the current page change. You can force the call to this method by calling `[_calendarManager reload];`.

```objective-c
- (void)calendar:(JTCalendarManager *)calendar prepareDayView:(JTCalendarDayView *)dayView
{
dayView.hidden = NO;

// Test if the dayView is from another month than the page
// Use only in month mode for indicate the day of the previous or next month
if([dayView isFromAnotherMonth]){
dayView.hidden = YES;
}
// Today
else if([_calendarManager.dateHelper date:[NSDate date] isTheSameDayThan:dayView.date]){
dayView.circleView.hidden = NO;
dayView.circleView.backgroundColor = [UIColor blueColor];
dayView.dotView.backgroundColor = [UIColor whiteColor];
dayView.textLabel.textColor = [UIColor whiteColor];
}
// Selected date
else if(_dateSelected && [_calendarManager.dateHelper date:_dateSelected isTheSameDayThan:dayView.date]){
dayView.circleView.hidden = NO;
dayView.circleView.backgroundColor = [UIColor redColor];
dayView.dotView.backgroundColor = [UIColor whiteColor];
dayView.textLabel.textColor = [UIColor whiteColor];
}
// Another day of the current month
else{
dayView.circleView.hidden = YES;
dayView.dotView.backgroundColor = [UIColor redColor];
dayView.textLabel.textColor = [UIColor blackColor];
}

// Your method to test if a date have an event for example
if([self haveEventForDay:dayView.date]){
dayView.dotView.hidden = NO;
}
else{
dayView.dotView.hidden = YES;
}
}
```

- `calendar:didTouchDayView:` this method is used to respond to a touch on a dayView. For example you can indicate to display another month if dayView is from another month.

```objective-c
- (void)calendar:(JTCalendarManager *)calendar didTouchDayView:(JTCalendarDayView *)dayView
{
// Use to indicate the selected date
_dateSelected = dayView.date;

// Animation for the circleView
dayView.circleView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1);
[UIView transitionWithView:dayView
duration:.3
options:0
animations:^{
dayView.circleView.transform = CGAffineTransformIdentity;
[_calendarManager reload];
} completion:nil];

// Load the previous or next page if touch a day from another month
if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
if([_calendarContentView.date compare:dayView.date] == NSOrderedAscending){
[_calendarContentView loadNextPageWithAnimation];
}
else{
[_calendarContentView loadPreviousPageWithAnimation];
}
}
}
```

### Switch to week view

If you want see just one week at a time, you have to set the `isWeekMode` to `YES` and reload the calendar.

```objective-c
_calendarManager.settings.weekModeEnabled = YES;
[_calendarManager reload];
```

#### WARNING

When you change the mode, it doesn't change the height of `calendarContentView`, you have to do it yourself.
See the Example project for more details.

### Customize the design

For customize the design you have to implement some methods depending of what parts you want to custom. Check the [JTCalendarDelegate](JTCalendar/JTCalendarDelegate.h) file and the Example project.

For example:

```objective-c
// This method is independent from the date, it's call only at the creation of the dayView.
// For customize the dayView depending of the date use `prepareDayView` method
- (UIView *)calendarBuildDayView:(JTCalendarManager *)calendar
{
JTCalendarDayView *view = [JTCalendarDayView new];
view.textLabel.font = [UIFont fontWithName:@"Avenir-Light" size:13];
view.textLabel.textColor = [UIColor blackColor];

return view;
}
```

### Pagination

The content views (`JTHorizontalCalendarView` and `JTVerticalCalendarView`) are just subclass of `UIScrollView`.
Each time the current page change, `calendarDidLoadNextPage` or `calendarDidLoadPreviousPage` is called.
The content views provide two method for display the previous or next page with an animation `loadNextPageWithAnimation` and `loadPreviousPageWithAnimation`.
You can limit the range of the calendar by implementing `canDisplayPageWithDate` method.

```objective-c
// Used to limit the date for the calendar
- (BOOL)calendar:(JTCalendarManager *)calendar canDisplayPageWithDate:(NSDate *)date
{
return [_calendarManager.dateHelper date:date isEqualOrAfter:_minDate andEqualOrBefore:_maxDate];
}
```

### Vertical calendar

If you use `JTVerticalCalendarView` for having a vertical calendar, you have some settings you have to set.

```objective-c
- (void)viewDidLoad
{
[super viewDidLoad];

_calendarManager = [JTCalendarManager new];
_calendarManager.delegate = self;

_calendarManager.settings.pageViewHaveWeekDaysView = NO; // You don't want WeekDaysView in the contentView
_calendarManager.settings.pageViewNumberOfWeeks = 0; // Automatic number of weeks

_weekDayView.manager = _calendarManager; // You set the manager for WeekDaysView
[_weekDayView reload]; // You load WeekDaysView manually

[_calendarManager setMenuView:_calendarMenuView];
[_calendarManager setContentView:_calendarContentView];
[_calendarManager setDate:[NSDate date]];

_calendarMenuView.scrollView.scrollEnabled = NO; // The scroll is not supported with JTVerticalCalendarView
}
```

### Internationalization / Localization (change first weekday)

For changing the locale and the timeZone just do:

```objective-c
_calendarManager.dateHelper.calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"CDT"];
_calendarManager.dateHelper.calendar.locale = [NSLocale localeWithLocaleIdentifier:@"fr_FR"];
[_calendarManager reload];
```
For changing locale and timeZone in Swift use:

```swift
let locale = Locale(identifier: "fr_FR")
let timeZone = TimeZone.init(abbreviation: "CDT")
calendarManager = JTCalendarManager(locale: locale, andTimeZone: timeZone)
```

### Date comparaison

Be careful when you compare two different dates, you have to take care of the time zone.
An helper is provided for some basic operations:

```objective-c
[_calendarManager.dateHelper date:dateA isTheSameMonthThan:dateB];
[_calendarManager.dateHelper date:dateA isTheSameWeekThan:dateB];
[_calendarManager.dateHelper date:dateA isTheSameDayThan:dateB];

// Use to limit the calendar range
[_calendarManager.dateHelper date:date isEqualOrAfter:minDate andEqualOrBefore:maxDate];

```

### Optimization

Every methods in the delegate are called in the main thread, you have to be really careful, in particular in the `prepareDayView` method which is called very often.

If you have to fetch some data from something slow, I recommend to create a cache and query this cache in `prepareDayView` method.
You have to cache the data from the next pages and update this cache asynchronously (in another thread via `dispatch_async`) when a new page is loaded (via `calendarDidLoadNextPage` and `calendarDidLoadPreviousPage` methods).

## Questions

Before asking any questions be sure to explore the Example project.
Check also [JTCalendarDelegate](JTCalendar/JTCalendarDelegate.h) and [JTCalendarSettings](JTCalendar/JTCalendarSettings.h) files.

Don't use `NSLog` to print date use a `NSDateFormatter`, `NSLog`doesn't take care of the timezone.

```objective-c
NSDateFormatter *dateFormatter = [_calendarManager.dateHelper createDateFormatter];
dateFormatter.dateFormat = @"yyyy'-'MM'-'dd' 'HH':'mm':'ss";
NSLog(@"%@", [dateFormatter stringFromDate:yourDate]);
```

## Requirements

- iOS 7 or higher
- Automatic Reference Counting (ARC)

## Author

- [Jonathan VUKOVICH TRIBOUHARET](https://github.com/jonathantribouharet) ([@johnvuko](https://twitter.com/johnvuko))

## License

JTCalendar is released under the MIT license. See the LICENSE file for more info.