JTCalendar 2.2.6

JTCalendar 2.2.6

测试测试
语言语言 Obj-CObjective C
许可证 MIT
发布上次发布2020年9月

Jonathan Vukovich Tribouharet 维护。




  • Jonathan VUKOVICH TRIBOUHARET

JTCalendar

CI Status Version Carthage compatible License Platform

JTCalendar 是一款适用于 iOS 的可自定义日历控件。

安装

使用 CocoaPods,将此行添加到您的 Podfile。

pod 'JTCalendar', '~> 2.0'

Carthage

要使用 Carthage 信任此项目,请将以下行添加到您的 Cartfile。

github "jonathantribouharet/JTCalendar" ~> 2.2

屏幕截图

Example Example

警告

第 2 张截图中日历下方的部分没有提供。

特点

  • 水平和垂直日历
  • 可高度自定义,可以通过继承默认类或创建自己的类来实现协议
  • 支持国际化
  • 周视图模式
  • 日期范围有限,您可以定义日历的开始日期和结束日期

用法

基本用法

您必须在您的 UIViewController 中创建两个视图

  • 第一个视图是 JTCalendarMenuView,它代表包含月份名称的部分。此视图是可选的。
  • 第二个视图是 JTHorizontalCalendarViewJTVerticalCalendarView,它代表日历本身。

您的 UIViewController 必须实现 JTCalendarDelegate,所有方法都是可选的。

#import <UIKit/UIKit.h>

#import <JTCalendar/JTCalendar.h>

@interface ViewController : UIViewController<JTCalendarDelegate>

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

@property (strong, nonatomic) JTCalendarManager *calendarManager;

@end

JTCalendarManager 用于协调 calendarMenuViewcalendarContentView 并提供默认行为。

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
        
    _calendarManager = [JTCalendarManager new];
    _calendarManager.delegate = self;
    
    [_calendarManager setMenuView:_calendarMenuView];
    [_calendarManager setContentView:_calendarContentView];
    [_calendarManager setDate:[NSDate date]];
}

@end

示例项目中包含了一些使用案例,您在提问前可以检查一下。

高级用法

即使 JTCalendarManager 的所有方法都是可选的,如果您不实现至少以下两个方法,您将无法取得很大进展:

  • calendar:prepareDayView: 此方法用于为特定日期自定义日视图的设计。每次在日视图中设置新的日期或每次当前页面更改时,都会调用此方法。您可以调用 [_calendarManager reload]; 来强制调用此方法。
- (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: 此方法用于响应对日视图的触摸。例如,如果您想显示另一个月份,如果日视图来自另一个月份。
- (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];
        }
    }
}

切换到周视图

如果您想要一次只查看一周,则需要将isWeekMode设置为YES并重新加载日历。

_calendarManager.settings.weekModeEnabled = YES;
[_calendarManager reload];

警告

当您更改模式时,它不会改变calendarContentView的高度,您需要自己操作。更多细节请参阅示例项目。

自定义设计

为了自定义设计,您需要根据要自定义的部分实现一些方法。请检查JTCalendarDelegate文件和示例项目。

例如

// 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<JTCalendarDay> *)calendarBuildDayView:(JTCalendarManager *)calendar
{
    JTCalendarDayView *view = [JTCalendarDayView new];
    view.textLabel.font = [UIFont fontWithName:@"Avenir-Light" size:13];
    view.textLabel.textColor = [UIColor blackColor];
    
    return view;
}

分页

内容视图(JTHorizontalCalendarViewJTVerticalCalendarView)仅仅是UIScrollView的子类。每次当前页面更改时,将会调用calendarDidLoadNextPagecalendarDidLoadPreviousPage。内容视图提供了两个用于显示前一页或下一页的方法,带有动画loadNextPageWithAnimationloadPreviousPageWithAnimation。您可以通过实现canDisplayPageWithDate方法来限制日历的范围。

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

垂直日历

如果您使用JTVerticalCalendarView创建垂直日历,您需要设置一些设置。

- (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
}

国际化/本地化(更改第一周的第一天)

要更改区域设置和时间区域,只需这样做

_calendarManager.dateHelper.calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"CDT"];
_calendarManager.dateHelper.calendar.locale = [NSLocale localeWithLocaleIdentifier:@"fr_FR"];
[_calendarManager reload];

在Swift中更改区域设置和时间区域请使用

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

日期比较

比较两个不同的日期时,要小心处理时区。提供了一些基本操作的辅助工具

[_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];

优化

委托中的每个方法都是在主线程中调用的,您必须非常小心,特别是在调用非常频繁的 prepareDayView 方法时。

如果您需要从某个慢速设备获取数据,我建议您创建一个缓存,并在 prepareDayView 方法中查询此缓存。您必须从下一页缓存数据,并在加载新页面时(通过 calendarDidLoadNextPagecalendarDidLoadPreviousPage 方法)异步(在另一个线程中通过 dispatch_async)更新此缓存。

问题

在提问之前,请确保探索示例项目。还要检查 JTCalendarDelegateJTCalendarSettings 文件。

不要使用 NSLog 打印日期,请使用 NSDateFormatter,因为 NSLog 并不处理时区。

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

要求

  • iOS 7 或更高版本
  • 自动引用计数 (ARC)

作者

授权

JTCalendar遵循MIT许可协议发布。有关更多信息,请参阅LICENSE文件。