KVKCalendar
KVKCalendar 是一个高度可定制的日历库。它包含五个模块,用于显示各种类型的日历(日、周、月、年、事件列表)。您可以选择任何模块或使用所有模块。它是基于标准 iOS 日历设计的,但增加了更多功能。时间轴显示了日和周的计划。
其他功能
- 切换时区
- 深色模式
- 骨架加载(月/列表)
- 自定义事件视图
- 自定义日期单元格
- 自定义标题视图和集合视图
- 自定义日历本地化
- 支持按周查看事件列表模式
- 设置分隔线(日/周)
- 支持在 iPad 上使用多个窗口
- 事件视图中支持 UIMenu(iOS 和 Mac Catalyst 14.0+)
- 配置查看事件框架的能力
需要帮助?
如果您在使用 KVKCalendar 的应用中遇到任何 问题,请使用 KVKCalendar 标签在 StackOverflow 上提问。
请,仅使用 Issues 来报告 bugs 或请求库中的新 功能。
要求
- iOS 13.0+、iPadOS 13.0+、MacOS 11.0+(支持Mac Catalyst)
- Swift 5.0+
安装
KVKCalendar 可以通过 CocoaPods、Carthage 或 Swift Package Manager 获取。
CocoaPods
pod 'KVKCalendar'
Carthage
github "kvyatkovskys/KVKCalendar"
Swift Package Manager(Xcode 12或更高版本)
- 在Xcode中,导航至 文件 → Swift包 → 添加包依赖...
- 选择一个项目
- 粘贴仓库URL(
https://github.com/kvyatkovskys/KVKCalendar.git
)并点击 下一步。 - 对于 规则,选择 版本(更新至下一个主要版本) 并点击 下一步。
- 点击 完成。
对于 UIKit 的使用方法
导入 KVKCalendar
。创建一个子类视图 CalendarView
并实现 CalendarDataSource
协议。创建一个 [Event]
类型的数组并返回数组。
import KVKCalendar
class ViewController: UIViewController {
var events = [Event]()
override func viewDidLoad() {
super.viewDidLoad()
let calendar = CalendarView(frame: frame)
calendar.dataSource = self
view.addSubview(calendar)
createEvents { (events) in
self.events = events
self.calendarView.reloadData()
}
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// to track changing frame when an user rotates device
calendarView.reloadFrame(view.frame)
}
}
extension ViewController {
func createEvents(completion: ([Event]) -> Void) {
let models = // Get events from storage / API
let events = models.compactMap({ (item) in
var event = Event(ID: item.id)
event.start = item.startDate // start date event
event.end = item.endDate // end date event
event.color = item.color
event.isAllDay = item.allDay
event.isContainsFile = !item.files.isEmpty
event.recurringType = // recurring event type - .everyDay, .everyWeek
// Add text event (title, info, location, time)
if item.allDay {
event.text = "\(item.title)"
} else {
event.text = "\(startTime) - \(endTime)\n\(item.title)"
}
return event
})
completion(events)
}
}
extension ViewController: CalendarDataSource {
func eventsForCalendar(systemEvents: [EKEvent]) -> [Event] {
// if you want to get events from iOS calendars
// set calendar names to style.systemCalendars = ["Test"]
let mappedEvents = systemEvents.compactMap { Event(event: $0) }
return events + mappedEvents
}
}
实现 CalendarDelegate
处理用户操作和控制日历行为。
calendar.delegate = self
如果您想使用特定事件或日期的自定义视图,则需要创建一个新的类为 EventViewGeneral
的视图并在函数中返回该视图。
class CustomViewEvent: EventViewGeneral {
override init(style: Style, event: Event, frame: CGRect) {
super.init(style: style, event: event, frame: frame)
}
}
// an optional function from CalendarDataSource
func willDisplayEventView(_ event: Event, frame: CGRect, date: Date?) -> EventViewGeneral? {
guard event.ID == id else { return nil }
return customEventView
}
要使用自定义日期单元格,只需订阅从 CalendarDataSource
中此可空方法(适用于日/周/月/年视图)。
func dequeueCell<T>(parameter: CellParameter, type: CalendarType, view: T, indexPath: IndexPath) -> KVKCalendarCellProtocol? where T: UIScrollView {
switch type {
case .year:
let cell = (view as? UICollectionView)?.dequeueCell(indexPath: indexPath) { (cell: CustomYearCell) in
// configure the cell
}
return cell
case .day, .week, .month:
let cell = (view as? UICollectionView)?.dequeueCell(indexPath: indexPath) { (cell: CustomDayCell) in
// configure the cell
}
return cell
case .list:
let cell = (view as? UITableView)?.dequeueCell { (cell: CustomListCell) in
// configure the cell
}
return cell
}
}
对于 SwiftUI 的使用方法
添加一个新的 SwiftUI
文件,导入 KVKCalendar
。创建一个名为 CalendarViewDisplayable
的结构体并声明用于将 UIKit
与 SwiftUI
连接的协议 UIViewRepresentable
。
import SwiftUI
import KVKCalendar
struct CalendarViewDisplayable: UIViewRepresentable {
@Binding var events: [Event]
var selectDate = Date()
var style = Style()
private var calendar = KVKalendarView(frame: .zero)
func makeUIView(context: UIViewRepresentableContext<CalendarViewDisplayable>) -> KVKCalendarView {
calendar.dataSource = context.coordinator
calendar.delegate = context.coordinator
return calendar
}
func updateUIView(_ uiView: KVKCalendarView, context: UIViewRepresentableContext<CalendarViewDisplayable>) {
context.coordinator.events = events
}
func makeCoordinator() -> CalendarDisplayView.Coordinator {
Coordinator(self)
}
public init(events: Binding<[Event]>) {
_events = events
calendar = KVKCalendarView(frame: frame, date: selectDate, style: style)
}
// MARK: Calendar DataSource and Delegate
class Coordinator: NSObject, CalendarDataSource, CalendarDelegate {
private let view: CalendarViewDisplayable
var events: [Event] = [] {
didSet {
view.events = events
view.calendar.reloadData()
}
}
init(_ view: CalendarViewDisplayable) {
self.view = view
super.init()
}
func eventsForCalendar(systemEvents: [EKEvent]) -> [Event] {
events
}
}
}
在另一个新的 SwiftUI
文件中,将 CalendarViewDisplayable
添加到 body
。
import SwiftUI
struct CalendarContentView: View {
@State var events: [Event] = []
var body: some View {
NavigationStack {
CalendarViewDisplayable(events: $events)
}
}
}
样式
要自定义日历,创建一个 Style
对象并将其添加到 CalendarView
的 init
类中。
public struct Style {
public var event = EventStyle()
public var timeline = TimelineStyle()
public var week = WeekStyle()
public var allDay = AllDayStyle()
public var headerScroll = HeaderScrollStyle()
public var month = MonthStyle()
public var year = YearStyle()
public var list = ListViewStyle()
public var locale = Locale.current
public var calendar = Calendar.current
public var timezone = TimeZone.current
public var defaultType: CalendarType?
public var timeHourSystem: TimeHourSystem = .twentyFourHour
public var startWeekDay: StartDayType = .monday
public var followInSystemTheme: Bool = false
public var systemCalendars: Set<String> = []
}
作者
许可证
KVKCalendar采用MIT许可证