ios - 如何在 SwiftUI 中实现自定义日历?
问题描述
我需要使用自定义日历而不是SwiftUI
DatePicker
. 为此,我pod 'KDCalendar', '~> 1.8.9'
在Podfile
该结构之后添加MyCalendar
了以下内容:
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))
}
}
推荐阅读
- python - Python 将 DXF 文件转换为 PDF 或 PNG 或 JPEG
- java - 查找保存 int number 所需的位数
- c - C中的多个矩阵运算
- java - 在 Gradle Jitpack 项目中构建 Java JNI
- android - 滚动时 FloatActionButton 不隐藏
- html - 如果重量太大或太小,我的代码不会发出警报
- perl - 如何为模具处理程序提供更多上下文?
- android - 如何避免使用@Overloads 重载 Main_activity OnCreate?
- python - 在动态树中使用 minidom 获取标签值
- java - 设置 calendar.day_of_month 就是设置 calendar.year