CalendarView

CalendarViewUICalendarView 的一个 SwiftUI 封装。UICalendarView 是一个显示日历的视图,允许用户选择单个或多个日期。它还允许显示特定日期的装饰。

有关其完整功能的更多信息,请参阅 Apple 的 UICalendarView 文档。

基本用法

使用 CalendarView 所需的最低要求是将其附加到具有 DateComponents 类型的 Binding 变量。 如果您希望将日期选择限制为一次一个日期,请使用可选的 DateComponents。 要允许多个日期选择,Binding 应该是一个 Set<DateComponents>DateComponentsSet)。

提示

如果您不需要跟踪任何选择,您也可以完全省略此参数。

另外,如果使用多项选择并且选择的顺序很重要,您可以使用 [DateComponents] 而不是 Set

struct ContentView: View {
    @State
    private var singleDateSelection: DateComponents? = nil

    @State
    private var multipleDateSelection: Set<DateComponents> = []

    var body: some View {
        VStack {
            // No selection tracking
            CalendarView()

            // Single date selection tracking
            CalendarView($singleDateSelection)

            // Multiple date selection tracking
            CalendarView($multipleDateSelection)
        }
    }
}

警告

CalendarView 外部更新 selection Binding 时,请务必小心。

如果您手动创建或更改从 CalendarView 输出的 DateComponents 实例,并且其中的组件与视图内部设置的组件不完全相同,您可能会遇到意外行为,例如重复选择等。

建议将 Binding 用作“只读”属性,而不是直接写入它。

高级配置

环境值

CalendarView 的一些元素可以使用 SwiftUI 的 Environment 及其标准的 ViewModifier (environment(_:_:)) 来设置。

这也意味着如果这些设置在父 Environment 中设置,CalendarView 也会对这些设置做出反应。 为了方便起见,该软件包还提供了缩写的修饰符来直接设置这些值。

这些元素是

CalendarView($selectedDate)
    // Environment Modifier
    // Calendar
    .environment(\.calendar, Calendar(identifier: .chinese))
    // Locale
    .environment(\.locale, Locale(identifier: "en_GB"))
    // Time Zone
    .environment(\.timeZone, TimeZone(identifier: "America/Chicago")!)

    // Convenience Modifiers
    // Calendar
    .calendar(Calendar(identifier: .chinese))
    // Locale
    .locale(Locale(identifier: "en_GB"))
    // Time Zone
    .timeZone(TimeZone(identifier: "America/Chicago")!)

更多配置

装饰

UICalendarView (因此,也间接通过 CalendarView) 的另一个功能是显示与日历中的任何日期相关的“装饰”。 这些装饰可以因日历中的不同日期而异,所有日期使用一种类型的装饰,或者根本不使用任何装饰。

不同的装饰类型如下

提示

您可以使用多个装饰修饰符为不同的日期(或未在其他修饰符中明确指定的所有日期)指定不同的装饰。

为特定日期明确指定的装饰优先于为未指定特定日期指定的装饰。

CalendarView($selectedDate)
    // This sets an orange `star.fill` symbol under all dates in the calendar.
    .decorations(.image("star.fill", color: .orange))
    // This displays the month number under each date (why not?) using a SwiftUI ViewBuilder
    .decorations { dateComponents in
        Text(dateComponents.month ?? 0, format: .number)
    }

字体设计

日历视图用于显示日历文本的字体设计。 CalendarView 附带一个 ViewModifier 来设置此项。

CalendarView($selectedDate)
    .fontDesign(.rounded)

可见日期组件

使用 CalendarView 初始化程序中的 visibleDateComponents 参数 (Binding<DateComponents?>),您可以控制日历视图中可见的部分。 它也可用于跟踪当前正在使用的日历部分。

struct ContentView: View {
    @State
    private var selectedDate: DateComponents? = nil

    // This sets the initial month shown to May 2024
    @State
    private var currentlyViewedComponents: DateComponents? = .init(
        calendar: calendar,
        year: 2024,
        month: 5
    )

    var body: some View {
        CalendarView(
            $selectedDate,
            visibleDateComponents: $currentlyViewedComponents
        )
    }
}

重要提示

如果 visibleDateComponentscalendar 属性设置为与视图的 calendar 不同的 Calendar(请参阅 环境值),则视图使用当前 Environmentcalendar,这可能导致来自日期组件的无效日期。

可用日期范围

使用 CalendarView 初始化程序中的 availableDateRange 参数 (DateInterval),您可以控制日历视图能够显示的日期范围。 设置此参数会限制日历视图显示的**最早**或**最晚**日期。 默认日期范围是从 distantPastdistantFuture

为了方便起见,该软件包附带一个额外的协议:DateRangeExpression,它允许从一些范围类型初始化 DateInterval。 此外,它还支持使用带有 Date 值的“Range-literal”语法来创建 DateInterval 值。 具体来说,它适用于以下语法

CalendarView(
    $selectedDate,
    // This would only allow the user to select
    // a date from the current moment in time onward.
    availableDateRange: Date.now...
)