[英]How to Implement Custom Calendar in SwiftUI?
我需要使用自定義日歷而不是SwiftUI
DatePicker
。 為此,我在創建的MyCalendar
結構之后的Podfile
中添加了pod 'KDCalendar', '~> 1.8.9'
,如下所示:
import SwiftUI
import KDCalendar
public struct MyCalendar: UIViewRepresentable {
public func makeUIView(context: Context) -> CalendarView {
return CalendarView()
}
public func updateUIView(_ calendar: CalendarView, context: Context) {
let date: Date = Date()
calendar.selectDate(date)
}
}
當我打算在任何堆棧中使用它時,它只顯示周名稱和日歷的其他部分,從視圖中省略,並發生以下錯誤:
[Assert] negative or zero item sizes are not supported in the flow layout
非常希望您的合作能夠解決這個問題。
您也可以嘗試FSCalendar 。 它有點復雜,有很多可配置選項。 請找到最簡單的FSCalendar實現如下:
import UIKit
import SwiftUI
import FSCalendar
MyCalendar().frame(minWidth: 200, minHeight: 320).padding(.leading, 5)
struct MyCalendar: UIViewControllerRepresentable {
func makeUIViewController(context: UIViewControllerRepresentableContext<MyCalendar>) -> MyCalendarController {
let calendar: MyCalendarController = .init()
return calendar
}
func updateUIViewController(_ calendar: MyCalendarController, context: UIViewControllerRepresentableContext<MyCalendar>) {
// MARK: - TODO
}
}
class MyCalendarController: UIViewController, FSCalendarDelegateAppearance {
let secondary: UIColor = .parse(0xE0B355)
let primary : UIColor = .parse(0x346C7C)
let tersiary : UIColor = .parse(0xE7EEEF)
fileprivate let formatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
fileprivate weak var calendar: FSCalendar!
override func loadView() {
let width: CGFloat = UIScreen.main.bounds.width - 40
let frame: CGRect = .init(x: 0, y: 0, width: width, height: 300)
let view: UIView = .init(frame: frame)
self.view = view
let calendar: FSCalendar = .init(frame: frame)
calendar.allowsMultipleSelection = false
calendar.dataSource = self
calendar.delegate = self
view.addSubview(calendar)
self.calendar = calendar
calendar.calendarHeaderView.backgroundColor = self.primary
calendar.calendarWeekdayView.backgroundColor = self.primary
calendar.appearance.headerTitleColor = self.tersiary
calendar.appearance.weekdayTextColor = self.tersiary
calendar.appearance.eventSelectionColor = self.tersiary
calendar.appearance.eventDefaultColor = self.primary
calendar.appearance.eventOffset = CGPoint(x: 0, y: -7)
calendar.appearance.todaySelectionColor = self.primary
calendar.appearance.selectionColor = self.secondary
calendar.appearance.todayColor = self.primary
calendar.appearance.titleWeekendColor = self.secondary
calendar.appearance.titleDefaultColor = self.primary
calendar.swipeToChooseGesture.isEnabled = true
let scopeGesture = UIPanGestureRecognizer(target: calendar, action: #selector(calendar.handleScopeGesture(_:)));
scopeGesture.delegate = self
calendar.addGestureRecognizer(scopeGesture)
}
override func viewDidLoad() {
super.viewDidLoad()
self.calendar.scope = .month
self.calendar.select(Date.init())
self.calendar.accessibilityIdentifier = "calendar"
}
}
extension MyCalendarController: FSCalendarDataSource {
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
debugPrint("did select date \(self.formatter.string(from: date))")
let selectedDates = calendar.selectedDates.map({self.formatter.string(from: $0)})
debugPrint("selected dates is \(selectedDates)")
if monthPosition == .next || monthPosition == .previous {
calendar.setCurrentPage(date, animated: true)
}
}
}
extension MyCalendarController: FSCalendarDelegate {
func calendar(_ calendar: FSCalendar, boundingRectWillChange bounds: CGRect, animated: Bool) {
self.calendar.frame.size.height = bounds.height
self.view.layoutIfNeeded()
}
}
extension MyCalendarController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
debugPrint("UIGestureRecognizer")
return true
}
}
extension UIColor {
static func parse(_ hex: UInt32, alpha: Double = 1.0) -> UIColor {
let red = CGFloat((hex & 0xFF0000) >> 16)/256.0
let green = CGFloat((hex & 0xFF00) >> 8)/256.0
let blue = CGFloat(hex & 0xFF)/256.0
return UIColor(red: red, green: green, blue: blue, alpha: CGFloat(alpha))
}
}
要查看KDCalendar ,只需添加數據源和委托,如下所示。 這將解決KDCalendar渲染問題。
import SwiftUI
import KDCalendar
public struct MyCalendar: UIViewRepresentable {
var date: Date = .init()
public func makeUIView(context: Context) -> CalendarView {
let calendar: CalendarView = .init()
calendar.setDisplayDate(self.date, animated: false)
calendar.selectDate(self.date)
calendar.dataSource = self
calendar.delegate = self
return calendar;
}
public func updateUIView(_ calendar: CalendarView, context: Context) {
calendar.selectDate(self.date)
}
}
extension MyCalendar: CalendarViewDataSource {
public func startDate() -> Date {
return Date.init()
}
public func endDate() -> Date {
var month:DateComponents = .init()
month.month = 2
return Calendar.current.date(byAdding: month, to: Date.init())!
}
public func headerString(_ date: Date) -> String? {
return nil
}
}
extension MyCalendar: CalendarViewDelegate {
public func calendar(_ calendar: CalendarView, didDeselectDate date: Date) {}
public func calendar(_ calendar: CalendarView, didScrollToMonth date: Date) {}
public func calendar(_ calendar: CalendarView, didSelectDate date: Date, withEvents events: [CalendarEvent]) {}
public func calendar(_ calendar: CalendarView, didLongPressDate date: Date, withEvents events: [CalendarEvent]?) {}
public func calendar(_ calendar: CalendarView, canSelectDate date: Date) -> Bool {
return true
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.