KVKCalendar 是一个高度可定制的日历。该库由五个模块组成,用于显示各种类型的日历(日、周、月、年、事件列表)。您可以选择任何模块或全部使用。它的设计基于标准的 iOS 日历,但具有额外的功能。时间轴显示当日和当周的日程安排。
附加功能
如果您在应用程序中如何使用 KVKCalendar 方面有问题,请使用 KVKCalendar 标签在 StackOverflow 上提问。
请仅使用 Issues 来报告 bug 或请求库中的新功能。
KVKCalendar 可通过 CocoaPods 或 Swift Package Manager 获取。
pod 'KVKCalendar'
https://github.com/kvyatkovskys/KVKCalendar
) 并单击 Next。导入 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
文件并导入 KVKCalendar
。创建一个结构体 CalendarViewDisplayable
并声明协议 UIViewRepresentable
用于连接 UIKit
和 SwiftUI
。
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
并添加到 init
类 CalendarView
。
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 许可证 下提供的