Skip to content

Customization

Colby Mehmen edited this page May 27, 2024 · 12 revisions

Customizing the Days Of Week Indicators

The Day Of Week Indicators are the column headers of the calendar month view. ex: M representing Monday and so on. You can use the defaults we provide or also provide your own custom implementation.

We will use ScrollableCalendarView as an example of how use our defaults or provide your own custom view. You will do this by accessing the calendarDayOfWeekInidcatorView parameter and passing in an instance of the type CalendarDayOfWeekIndicatorView.

Below is an example of passing in the default .abbreviated().

ScrollableCalendarView(
    viewModel: viewModel,
    calendarDayOfWeekInidcatorView: .abbreviated() // <<-- Here
)

This will give us the following result, Day Of Week Indicators with 3 letter abbreviations of the days of week.

Below are other options available, all are straight forward and work the same except for the .custom(_) implementation.

public enum CalendarDayOfWeekIndicatorView<DayOfWeekIndicatorView: View> {
    case custom((DayOfWeek) -> (DayOfWeekIndicatorView)) // your own custom view
    case singleLetter(DayOfWeekIndicatorView = EmptyView()) // single letter indicator
    case abbreviated(DayOfWeekIndicatorView = EmptyView()) // three letter indicator
}

The custom(_). implementation will give you a completion handler that gives you the DayOfWeek (ex: Monday) and then you will have to return the custom view to be presented.

            ScrollableCalendarView(
                viewModel: viewModel,
                calendarDayOfWeekInidcatorView: .custom({ dayOfWeek in 
                    customDayOfWeekIndicatorView(dayOfWeek: dayOfWeek) // <<-- Your custom implementation (example below)
                })
            )

Below is an example of custom day day of week indicator view.

    private func customDayOfWeekIndicatorView(dayOfWeek: DayOfWeek) -> some View {
        ZStack {
            Color.gray.opacity(0.33)
                .cornerRadius(5.0)
            Text(dayOfWeek.abbreviated)
                .font(.system(.body, design: .rounded, weight: .semibold))
        }
    }

Customizing Month Header View

You have complete access to the calendar month headers. This is usually where you will want to display the months name. You might want to add additional information, actionable items, or just your custom fonts. All is possible by accessing the calendarHeaderView parameter.

We will be using the ScollableCalendarView class to demonstrate this, but this will also work using CalendarMonthView (which displays just a singular month).

The below code is going to get us the following result, a simple calendar with a header view of the month name.

ScrollableCalendarView(
    viewModel: viewModel,
    calendarDayView: .custom({ calendarDay in
        customCalendarDayView(calendarDay)
    })
)

To customize further you will need to user the calendarHeaderView parameter, below is an example of where to add it. By default it is set to show the month name only.

            ScrollableCalendarView(
                viewModel: viewModel,
                calendarHeaderView: <CalendarMonthHeaderView<HeaderView>>, // Customize here
                calendarDayView: .custom({ calendarDay in
                    customCalendarDayView(calendarDay)
                })
            )

The parameter is of type CalendarMonthHeaderView, this provides some default options and a custom option to give you full access to what is displayed.

public enum CalendarMonthHeaderView<HeaderView: View> {
    case custom((CalendarMonth) -> (HeaderView))
    case monthLabel(HeaderView = EmptyView())
    case monthYearLabel(HeaderView = EmptyView())
}
  • .custom(_) // provides a completion handler that returns a custom view.
  • .monthLabel // This will display only the month name, ex: "May"
  • .monthYearLabel // Will display month and year, ex: "May 2024"

Custom Header View Example

When using the .custom implementation you will receive a CalendarMonth object that will provide you with information to help customize your month header view. Below is an example of doing so.

            ScrollableCalendarView(
                viewModel: viewModel,
                calendarHeaderView: .custom({ calendarMonth in
                    HStack {
                        VStack(alignment: .leading, spacing: 0.0) {
                            Text(calendarMonth.title)
                                .font(.system(.title2, design: .rounded, weight: .bold))
                            
                            HStack(spacing: 0.0) {
                                Image(systemName: "arrow.up")
                                    .font(.caption)
                                    .foregroundStyle(.green)
                                    .padding(4)
                                    .bold()
                                Text("$432.44")
                                    .font(.caption)
                                    .bold()
                            }
                        }
                        Spacer()
                    }
                    .padding(.leading)
                }),
                calendarDayView: .custom({ calendarDay in
                    customCalendarDayView(calendarDay)
                })
            )

Customizing Calendar Days

Implementing Calendar Style (Custom Implementation)

When choosing to use the custom implementation your code will look like the following. The Custom implementation provides a completion handler where you will return the CalendarDay of the view you need to draw, which gives you all you need to create your custom calendar day view, and then you will have to return the View.

var body: some View {
    ScrollableCalendarView(
        viewModel: viewModel,
        calendarDayView: .custom( // <--- HERE
            { calendarDay in
                // Your custom view implementation here
            }
        )
    )
}

Now you will need to provide your custom view to the completion handle. The CalendarDay is going to be vital for doing so. I recommend creating a function that takes in a CalendarDay parameter and returns a view. Forexample:

private func customCalendarDayView(_ calendarDay: CalendarDay) -> some View {
    ZStack {
        RoundedRectangle(cornerRadius: 10.0)
            .foregroundStyle(Color.gray.opacity(0.13))
        Text(calendarDay.descriptor) // The day number. ex: 11
            .bold()
    }
    .aspectRatio(contentMode: .fit)
}

This function will return a rounded rectangle with the numbered day of month centered on top of it.

Next you will need to put this function inside the completion handler.

var body: some View {
    ScrollableCalendarView(
        viewModel: viewModel,
        calendarDayView: .custom(
            { calendarDay in
                customCalendarDayView(calendarDay) // <-- HERE
            }
        )
    )
}

This will be the result of the above code.