Home

Awesome

OBCalendar

Documentation and Tutorial

Example Designs

<div align="center"> <table> <tr> <td><img width=300 src="https://github.com/oBilet/OBCalendarDocument/blob/main/docs/images/obcalendar.ObiletCalendar/firstSS.png"></td> <td><img width=300 src="https://github.com/oBilet/OBCalendarDocument/blob/main/docs/images/obcalendar.ObiletCalendar/secondSS.png"></td> <td><img width=300 src="https://github.com/oBilet/OBCalendarDocument/blob/main/docs/images/obcalendar.ObiletCalendar/thirdSS.png"></td> </tr> <tr> <td><img width=300 src="https://github.com/oBilet/OBCalendarDocument/blob/main/docs/images/obcalendar.ObiletCalendar/fourthSS.png"></td> <td><img width=300 src="https://github.com/oBilet/OBCalendarDocument/blob/main/docs/images/obcalendar.ObiletCalendar/fifthSS.png"></td> <td><img width=300 src="https://github.com/oBilet/OBCalendarDocument/blob/main/docs/images/obcalendar.ObiletCalendar/sixthSS.png"></td> </tr> </table> </div>

Requirements

Installation

To integrate OBCalendar into your project using Swift Package Manager, follow these steps:

Note

For better performance, use lazyDays: true and lazyMonths: true. If you are using programmatic scroll, set lazyYears: false because subviews need to be loaded into memory once for ScrollViewProxy to recognize their id values.

Usage

Default:

// 1 year of drawing range
OBCalendar(drawingRange: .year(1))

// 3 months of drawing range
OBCalendar(drawingRange: .month(3))

// 60 days of drawing range
OBCalendar(drawingRange: .day(60))

Double selection example:

OBCalendar()
   .dayModifier { baseView, model in
      let date = model.day.date
      let targetView = baseView
         .onTapGesture {
            if firstSelectedDate == nil {
               firstSelectedDate = date
            } else if secondSelectedDate == nil {
               secondSelectedDate = date
            } else {
               secondSelectedDate = nil
               firstSelectedDate = date
            }
         }
   
      if date == firstSelectedDate {
         targetView
            .background(firstSelectedBackground)
      } else if date == secondSelectedDate {
         targetView
            .background(secondSelectedBackground)
      } else if isBetweenSelected(date: date) { //date > firstSelectedDate && date < secondSelectedDate
         targetView
            .background(betweenSelectedBackground)
      } else {
         targetView
      }
   }

Horizontal Scroll:

GeometryReader { geometry in
      OBCalendar(
          monthScrollAxis: .horizontal,
          yearScrollAxis: .horizontal
      )
      .monthModifier { baseView, daysView, model in
          baseView
              .padding()
              .frame(width: geometry.size.width)
      }
}

DayModifier:

 OBCalendar()
      .dayModifier { baseView, model in
          baseView
              .background(Color.blue)
              .padding(2)
              .foregroundColor(.white)
      }

MonthModifier:

OBCalendar()
      .monthModifier{ baseView, daysView, model in
          VStack {
              Text("Modified Months")
              daysView
          }
          .padding()
      }

Modified Day + Modified Month:

OBCalendar()
      .dayModifier { baseView, model in
          baseView
              .foregroundColor(Color(.red))
      }
      .monthModifier { baseView, daysView, model in
          VStack {
              Text("Modified Months")
              daysView
          }
          .padding()
      }

BaseCalendar

let today = Date()
let twoYearsLater = calendar.date(byAdding: .year, value: 2, to: today)!

OBBaseCalendar(startDate: today, endDate: twoYearsLater) { model, scrollProxy in
    // day view goes here
    let day = model.day
    Text("\(day.day)")
} monthContent: { model, scrollProxy, daysView in
    // month view goes here
    daysView
} yearContent: { model, scrollProxy, monthsView in
    // year view goes here
    monthsView
}

BaseCalendar + Custom layouts

//Implement your own layout
let years = [CalendarModel.Year]() 

// Or use default layout
let defaultLayout = CalendarModelBuilder.defaultLayout(
      calendar: .current,
      startDate: Date(),
      endDate: Date().addingTimeInterval(3600 * 24 * 365)
)

OBBaseCalendar(years: years) { model, scrollProxy in
    // day view goes here
    let day = model.day
    Text("\(day.day)")
} monthContent: { model, scrollProxy, daysView in
    // month view goes here
    daysView
} yearContent: { model, scrollProxy, monthsView in
    // year view goes here
    monthsView
}

Feel free to explore the SwiftUI-powered flexibility of OBCalendar to meet your custom calendar needs!