首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在SwiftUI中实现自定义日历?

如何在SwiftUI中实现自定义日历?
EN

Stack Overflow用户
提问于 2020-01-21 04:52:13
回答 2查看 5.3K关注 0票数 2

我需要使用自定义日历而不是SwiftUI DatePicker。为此,我在创建的pod 'KDCalendar', '~> 1.8.9'结构之后添加了Podfile中的MyCalendar,如下所示:

代码语言:javascript
运行
复制
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)
    }
}

当我打算在任何堆栈中使用它时,它只显示周名称和日历的其他部分,从视图中省略,并且发生了以下错误:

代码语言:javascript
运行
复制
[Assert] negative or zero item sizes are not supported in the flow layout

你们的合作很有希望解决这个问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-09-02 08:05:45

你也可以试试FSCalendar。在有很多可配置选项的情况下,这有点复杂。请找到FSCalendar的最简单实现如下:

用法

代码语言:javascript
运行
复制
import UIKit
import SwiftUI
import FSCalendar

MyCalendar().frame(minWidth: 200, minHeight: 320).padding(.leading, 5)

MyCalendar

代码语言:javascript
运行
复制
struct MyCalendar: UIViewControllerRepresentable {
    func makeUIViewController(context: UIViewControllerRepresentableContext<MyCalendar>) -> MyCalendarController {
        let calendar: MyCalendarController = .init()
        return calendar
    }

    func updateUIViewController(_ calendar: MyCalendarController, context: UIViewControllerRepresentableContext<MyCalendar>) {
        // MARK: - TODO
    }
}     

MyCalendarController

代码语言:javascript
运行
复制
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"
    }
}

扩展

代码语言:javascript
运行
复制
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))
    }
}
票数 4
EN

Stack Overflow用户

发布于 2020-05-12 06:22:46

要查看KDCalendar,只需添加dataSource委托,如下所示。这将解决KDCalendar呈现问题。

代码语言:javascript
运行
复制
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
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59834349

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档