SwiftUI 的水平单行日历。来自 Fit Records
FRHorizontalCalendar 可通过 SPM 安装
将其添加为新的包依赖项,地址为 https://github.com/emrepun/FRHorizontalCalendar
FRHorizontalCalendar 使用视图模型,该视图模型必须由您提供。 但是它非常简单。
在您的视图的可观察对象中,您将使用日历视图,初始化一个 FRHorizontalCalendarViewModel 的实例。
然后在视图的初始化器中将此视图模型传递给 FRHorizontalCalendar。
如果您想收到来自某些事件的通知,例如日期选择和日期出现,那么通过遵守 FRCalendarObserving 将您的对象设置为 FRHorizontalCalendarViewModel 的代理。它的一些方法是可选的,因此请务必查看所有方法。
可以突出显示某些日期,这些日期上有一些内容可用。只需调用 setContentAvailableForDaysWithGivenDates(_ dates: [Date]) 并传递要突出显示日历的日期。您无需担心日期的确切时间或重复项,日历会处理这些。
您可能想要从先前设置内容可用的日期中删除内容可用性。例如,当用户删除某些数据时。在这种情况下,调用 removeContentAvailableForDayWithGivenDate(_ date: Date)。
FRHorizontalCalendar 在内部使用 ScrollView,因此,如果您将其添加到可滚动视图(如 List、ScrollView 等)中,则必须为其设置高度。否则,日历视图将无法正确布局自身,并且日期选择动画也会中断。但是我们也为您提供了此案例的解决方案。
在符合 FRCalendarObserving 的对象中实现 didSetInitialHeight(_ height: CGFloat),并在每次触发时,将高度设置为已发布的属性,视图包含日历的位置可以相应地设置日历的框架。此外,请确保将日历视图包装在 VStack 或另一个视图中,以修复日期选择动画。请参阅下面的示例
// Your observable object (view model)
final class ExampleViewWithCalendarViewModel: ObservableObject, FRCalendarObserving {
let calendarViewModel: FRHorizontalCalendarViewModel
@Published var calendarHeight: CGFloat?
init() {
let components = DateComponents(year: 2023, month: 1, day: 1)
let startDate = Calendar.current.date(from: components)!
self.calendarViewModel = .init(startDate: startDate)
calendarViewModel.delegate = self
}
func didSetInitialHeight(_ height: CGFloat) {
calendarHeight = height
}
}
// Your parent view (that contains calendar)
struct ExampleViewWithCalendarView: View {
@StateObject var viewModel = ExampleViewWithCalendarViewModel()
var body: some View {
List {
VStack {
FRHorizontalCalendarView(viewModel: viewModel.calendarViewModel)
.frame(height: viewModel.calendarHeight ?? 200.0)
}
}
.listStyle(.plain)
}
}
有关使用和设置的更多详细信息,请参见示例项目。
目前,没有为 FRHorizontalCalendarViewModel 提供模拟。这意味着,当您初始化它并从视图模型中保留对它的引用时,如果您为该视图模型编写单元测试。您将无法模拟它。因此,您将无法验证您的对象是否按预期与日历视图模型交互。我希望尽快进行必要的更改和重构以实现此目的。但是总是欢迎任何贡献 :)