### Setup WeekCalendarView with WeekDayBinder
Source: https://context7.com/kizitonwose/calendar/llms.txt
Shows how to set up a WeekCalendarView, including defining a custom view container for week days and binding data. Also includes an example of a scroll listener.
```kotlin
// res/layout/fragment_week.xml (abbreviated)
//
```
```kotlin
class WeekDayContainer(view: View) : ViewContainer(view) {
val textView: TextView = view.findViewById(R.id.weekDayText)
lateinit var weekDay: WeekDay
init {
view.setOnClickListener { /* use weekDay */ }
}
}
```
```kotlin
val today = LocalDate.now()
weekCalendarView.dayBinder = object : WeekDayBinder {
override fun create(view: View) = WeekDayContainer(view)
override fun bind(container: WeekDayContainer, data: WeekDay) {
container.weekDay = data
container.textView.text = data.date.dayOfMonth.toString()
}
}
```
```kotlin
weekCalendarView.weekScrollListener = {
// Called when scrolled to a new week (calendarScrollPaged = true)
Log.d("Calendar", "Visible week: ${it.days.first().date}")
}
```
```kotlin
weekCalendarView.setup(
today.minusDays(365),
today.plusDays(365),
firstDayOfWeekFromLocale(),
)
weekCalendarView.scrollToWeek(today)
// weekCalendarView.smoothScrollToWeek(today) // animated
```
--------------------------------
### Setup CalendarView
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Configure the visible date range and scroll to the current month for CalendarView. Ensure `firstDayOfWeekFromLocale()` is available.
```kotlin
val currentMonth = YearMonth.now()
val startMonth = currentMonth.minusMonths(100) // Adjust as needed
val endMonth = currentMonth.plusMonths(100) // Adjust as needed
val firstDayOfWeek = firstDayOfWeekFromLocale() // Available from the library
calendarView.setup(startMonth, endMonth, firstDayOfWeek)
calendarView.scrollToMonth(currentMonth)
```
--------------------------------
### Implementing Date Selection
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Example demonstrating how to implement date selection logic by updating the UI based on a selected date state.
```APIDOC
## Implementing Date Selection
### Day Composable with Selection Styling
```kotlin
@Composable
fun Day(day: CalendarDay, isSelected: Boolean, onClick: (CalendarDay) -> Unit) {
Box(
modifier = Modifier
.aspectRatio(1f)
.clip(CircleShape)
.background(color = if (isSelected) Color.Green else Color.Transparent)
.clickable(
enabled = day.position == DayPosition.MonthDate,
onClick = { onClick(day) }
)
) {
Text(text = day.date.dayOfMonth.toString())
}
}
```
### MainScreen with Date Selection State
```kotlin
@Composable
fun MainScreen() {
var selectedDate by remember { mutableStateOf(null) }
HorizontalCalendar(
state = state,
dayContent = { day ->
Day(day, isSelected = selectedDate == day.date) { day ->
selectedDate = if (selectedDate == day.date) null else day.date
}
}
)
}
```
```
--------------------------------
### Setup YearCalendarView
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Configure the year range and scroll to the current year for YearCalendarView. This involves XML layout definition and Kotlin setup.
```xml
```
```kotlin
val currentYear = Year.now()
val startYear = currentYear.minusYears(100) // Adjust as needed
val endYear = currentYear.plusYears(100) // Adjust as needed
val firstDayOfWeek = firstDayOfWeekFromLocale() // Available from the library
yearCalendarView.setup(startYear, endYear, firstDayOfWeek)
yearCalendarView.scrollToYear(currentYear)
```
--------------------------------
### HorizontalCalendar and VerticalCalendar Setup
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Set up the state for HorizontalCalendar or VerticalCalendar. Adjust start and end months to define the calendar's navigable range. Ensure `firstDayOfWeek` is correctly determined for locale.
```kotlin
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import com.kizitonwose.calendar.compose.HorizontalCalendar
import com.kizitonwose.calendar.compose.rememberCalendarState
import com.kizitonwose.calendar.core.CalendarDay
import com.kizitonwose.calendar.core.firstDayOfWeekFromLocale
import java.time.YearMonth
@Composable
fun MainScreen() {
val currentMonth = remember { YearMonth.now() }
val startMonth = remember { currentMonth.minusMonths(100) } // Adjust as needed
val endMonth = remember { currentMonth.plusMonths(100) } // Adjust as needed
val firstDayOfWeek = remember { firstDayOfWeekFromLocale() } // Available from the library
val state = rememberCalendarState(
startMonth = startMonth,
endMonth = endMonth,
firstVisibleMonth = currentMonth,
firstDayOfWeek = firstDayOfWeek
)
HorizontalCalendar(
state = state,
dayContent = { Day(it) }
)
// If you need a vertical calendar.
// VerticalCalendar(
// state = state,
// dayContent = { Day(it) }
// )
}
```
--------------------------------
### Get Days of Week with Custom First Day
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Generates a list of `DayOfWeek` starting from a specified day. This allows you to customize the order of weekdays displayed.
```kotlin
val daysOfWeek = daysOfWeek(firstDayOfWeek = DayOfWeek.THURSDAY)
// Will produce => Thu | Fri | Sat | Sun | Mon | Tue | Wed
```
--------------------------------
### HorizontalYearCalendar and VerticalYearCalendar Setup
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Initialize the state for year-based calendars. Set the start and end years to define the navigable range and specify the initially visible year. Use `firstDayOfWeekFromLocale` for correct day-of-week display.
```kotlin
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.kizitonwose.calendar.compose.HorizontalYearCalendar
import com.kizitonwose.calendar.compose.rememberYearCalendarState
import com.kizitonwose.calendar.core.firstDayOfWeekFromLocale
import java.time.Year
@Composable
fun MainScreen() {
val currentYear = remember { Year.now() }
val startYear = remember { currentYear.minusYears(100) } // Adjust as needed
val endYear = remember { currentYear.plusYears(100) } // Adjust as needed
val firstDayOfWeek = remember { firstDayOfWeekFromLocale() } // Available from the library
val state = rememberYearCalendarState(
startYear = startYear,
endYear = endYear,
firstVisibleYear = currentYear,
firstDayOfWeek = firstDayOfWeek,
)
HorizontalYearCalendar(
state = state,
dayContent = { Day(it) },
)
// If you need a vertical year calendar.
// VerticalYearCalendar(
// state = state,
// dayContent = { Day(it) }
// )
}
```
--------------------------------
### Basic Horizontal Year Calendar Usage
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Demonstrates the basic setup for a horizontal year calendar. Ensure you have the necessary imports for Year, remember, and firstDayOfWeekFromLocale.
```kotlin
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.kizitonwose.calendar.core.Year
import com.kizitonwose.calendar.core.firstDayOfWeekFromLocale
import com.kizitonwose.calendar.yearcalendar.HorizontalYearCalendar
import com.kizitonwose.calendar.yearcalendar.YearCalendarState
import com.kizitonwose.calendar.yearcalendar.rememberYearCalendarState
@Composable
fun MainScreen() {
val currentYear = remember { Year.now() }
val startYear = remember { currentYear.minusYears(100) } // Adjust as needed
val endYear = remember { currentYear.plusYears(100) } // Adjust as needed
val firstDayOfWeek = remember { firstDayOfWeekFromLocale() } // Available from the library
val state = rememberYearCalendarState(
startYear = startYear,
endYear = endYear,
firstVisibleYear = currentYear,
firstDayOfWeek = firstDayOfWeek,
)
HorizontalYearCalendar(
state = state,
dayContent = { Day(it) },
yearHeader = { YearHeader(it) },
monthHeader = { MonthHeader(it) },
)
// If you need a vertical year calendar.
// VerticalYearCalendar(
// state = state,
// dayContent = { Day(it) }
// )
}
```
--------------------------------
### WeekCalendar Setup
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Configure the state for a WeekCalendar. Define the date range and the initially visible week. `firstDayOfWeek` should be set according to the user's locale.
```kotlin
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.kizitonwose.calendar.compose.WeekCalendar
import com.kizitonwose.calendar.compose.rememberWeekCalendarState
import com.kizitonwose.calendar.core.firstDayOfWeekFromLocale
import java.time.LocalDate
import java.time.YearMonth
@Composable
fun MainScreen() {
val currentDate = remember { LocalDate.now() }
val currentMonth = remember { YearMonth.now() }
val startDate = remember { currentMonth.minusMonths(100).atStartOfMonth() } // Adjust as needed
val endDate = remember { currentMonth.plusMonths(100).atEndOfMonth() } // Adjust as needed
val firstDayOfWeek = remember { firstDayOfWeekFromLocale() } // Available from the library
val state = rememberWeekCalendarState(
startDate = startDate,
endDate = endDate,
firstVisibleWeekDate = currentDate,
firstDayOfWeek = firstDayOfWeek
)
WeekCalendar(
state = state,
dayContent = { Day(it) }
)
}
```
--------------------------------
### Setup CalendarView with MonthDayBinder and MonthHeaderBinder
Source: https://context7.com/kizitonwose/calendar/llms.txt
Demonstrates setting up CalendarView in XML, defining custom view containers for days and month headers, and binding data to them. Requires `cv_dayViewResource` and `cv_monthHeaderResource` in XML.
```kotlin
// res/layout/fragment_calendar.xml (abbreviated)
//
```
```kotlin
// DayViewContainer.kt
class DayViewContainer(view: View) : ViewContainer(view) {
val textView: TextView = view.findViewById(R.id.calendarDayText)
lateinit var day: CalendarDay
init {
view.setOnClickListener {
if (day.position == DayPosition.MonthDate) {
// handle click
}
}
}
}
```
```kotlin
// Fragment / Activity setup
val currentMonth = YearMonth.now()
val daysOfWeek = daysOfWeek()
calendarView.dayBinder = object : MonthDayBinder {
override fun create(view: View) = DayViewContainer(view)
override fun bind(container: DayViewContainer, data: CalendarDay) {
container.day = data
container.textView.text = data.date.dayOfMonth.toString()
container.textView.setTextColor(
if (data.position == DayPosition.MonthDate) Color.BLACK else Color.LTGRAY
)
}
}
```
```kotlin
// Month header showing day-of-week titles
class MonthHeaderContainer(view: View) : ViewContainer(view) {
val titlesRow = view as ViewGroup
}
calendarView.monthHeaderBinder = object : MonthHeaderFooterBinder {
override fun create(view: View) = MonthHeaderContainer(view)
override fun bind(container: MonthHeaderContainer, data: CalendarMonth) {
if (container.titlesRow.tag == null) {
container.titlesRow.tag = true
container.titlesRow.children.map { it as TextView }.forEachIndexed { i, tv ->
tv.text = daysOfWeek[i].getDisplayName(TextStyle.SHORT, Locale.getDefault())
}
}
}
}
```
```kotlin
calendarView.setup(
currentMonth.minusMonths(100),
currentMonth.plusMonths(100),
daysOfWeek.first()
)
calendarView.scrollToMonth(currentMonth)
```
--------------------------------
### Setup WeekCalendarView
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Configure the date range and scroll to the current date for WeekCalendarView. This requires setting up the view in XML and then configuring it in Kotlin.
```xml
```
```kotlin
val currentDate = LocalDate.now()
val currentMonth = YearMonth.now()
val startDate = currentMonth.minusMonths(100).atStartOfMonth() // Adjust as needed
val endDate = currentMonth.plusMonths(100).atEndOfMonth() // Adjust as needed
val firstDayOfWeek = firstDayOfWeekFromLocale() // Available from the library
weekCalendarView.setup(startDate, endDate, firstDayOfWeek)
weekCalendarView.scrollToWeek(currentDate)
```
--------------------------------
### Handling Date Clicks
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Example of how to handle date clicks within a Day composable using the clickable modifier.
```APIDOC
## Handling Date Clicks
### Day Composable with Click Handling
```kotlin
@Composable
fun Day(day: CalendarDay, onClick: (CalendarDay) -> Unit) {
Box(
modifier = Modifier
.aspectRatio(1f)
.clickable(
enabled = day.position == DayPosition.MonthDate,
onClick = { onClick(day) }
)
) {
Text(text = day.date.dayOfMonth.toString())
}
}
```
```
--------------------------------
### Week Calendar Example
Source: https://context7.com/kizitonwose/calendar/llms.txt
Displays a horizontally scrolling week calendar, showing one week at a time. State is managed via `rememberWeekCalendarState`. Customize day appearance and handle selection.
```kotlin
import android.icu.util.Locale
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.kizitonwose.calendar.compose.WeekCalendar
import com.kizitonwose.calendar.compose.rememberWeekCalendarState
import com.kizitonwose.calendar.core.firstDayOfWeekFromLocale
import java.time.LocalDate
import java.time.YearMonth
import java.time.format.TextStyle
@Composable
fun WeekCalendarScreen() {
val today = remember { LocalDate.now() }
val currentMonth = remember { YearMonth.now() }
val startDate = remember { currentMonth.minusMonths(12).atStartOfMonth() }
val endDate = remember { currentMonth.plusMonths(12).atEndOfMonth() }
val state = rememberWeekCalendarState(
startDate = startDate,
endDate = endDate,
firstVisibleWeekDate = today,
firstDayOfWeek = firstDayOfWeekFromLocale(),
)
var selectedDate by remember { mutableStateOf(today) }
WeekCalendar(
state = state,
dayContent = { weekDay ->
val isSelected = weekDay.date == selectedDate
Column(
modifier = Modifier
.weight(1f)
.padding(4.dp)
.clip(RoundedCornerShape(8.dp))
.background(if (isSelected) MaterialTheme.colorScheme.primary else Color.Transparent)
.clickable { selectedDate = weekDay.date },
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
weekDay.date.dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.getDefault()),
style = MaterialTheme.typography.labelSmall,
color = if (isSelected) Color.White else Color.Gray,
)
Text(
weekDay.date.dayOfMonth.toString(),
style = MaterialTheme.typography.bodyLarge,
color = if (isSelected) Color.White else Color.Black,
)
}
},
)
}
```
--------------------------------
### Define Custom Day View Layout
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Create a layout file for individual date cells in the calendar. This example uses a TextView to display the day number.
```xml
```
--------------------------------
### Setup CalendarView with DaysOfWeek
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Configure CalendarView using a list of days of the week, ensuring the first day matches the locale or custom setting. This is used in conjunction with setting up weekday titles.
```kotlin
val daysOfWeek = daysOfWeek()
calendarView.setup(startMonth, endMonth, daysOfWeek.first())
```
--------------------------------
### Locale-Aware Week Utilities
Source: https://context7.com/kizitonwose/calendar/llms.txt
Helper functions to get a list of `DayOfWeek` values based on the current locale or a specified starting day. Useful for configuring calendar headers and states.
```kotlin
// Returns 7 DayOfWeek values starting from the locale default (e.g. Sun for en-US, Mon for most of Europe)
val daysOfWeek: List = daysOfWeek()
// Returns 7 DayOfWeek values starting from Thursday
val daysOfWeekFromThursday: List = daysOfWeek(firstDayOfWeek = DayOfWeek.THURSDAY)
// => [THURSDAY, FRIDAY, SATURDAY, SUNDAY, MONDAY, TUESDAY, WEDNESDAY]
// Use for both calendar state initialization and column header rendering
val firstDay: DayOfWeek = firstDayOfWeekFromLocale() // shortcut for daysOfWeek().first()
```
--------------------------------
### Year Calendar View Setup and Binding
Source: https://context7.com/kizitonwose/calendar/llms.txt
Defines a custom view container for year day cells and sets up the day binder for the YearCalendarView. Use this to customize the appearance and behavior of individual days within the year view.
```kotlin
// res/layout/fragment_year.xml (abbreviated)
//
class YearDayContainer(view: View) : ViewContainer(view) {
val textView: TextView = view.findViewById(R.id.yearDayText)
}
val currentYear = Year.now()
yearCalendarView.dayBinder = object : MonthDayBinder {
override fun create(view: View) = YearDayContainer(view)
override fun bind(container: YearDayContainer, data: CalendarDay) {
container.textView.text = data.date.dayOfMonth.toString()
container.textView.alpha = if (data.position == DayPosition.MonthDate) 1f else 0.3f
}
}
// Notify a single date change after updating selection state
fun onDateSelected(date: LocalDate) {
val previousSelection = selectedDate
selectedDate = date
previousSelection?.let { yearCalendarView.notifyDateChanged(it) }
yearCalendarView.notifyDateChanged(date)
}
yearCalendarView.setup(
currentYear.minusYears(5),
currentYear.plusYears(5),
firstDayOfWeekFromLocale(),
)
yearCalendarView.scrollToYear(currentYear)
```
--------------------------------
### Vertical Month Calendar Example
Source: https://context7.com/kizitonwose/calendar/llms.txt
Displays a vertically scrolling month calendar. Set `calendarScrollPaged` to `false` for free-form scrolling. Customize day and month header appearance.
```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.kizitonwose.calendar.compose.VerticalCalendar
import com.kizitonwose.calendar.compose.rememberCalendarState
import com.kizitonwose.calendar.core.firstDayOfWeekFromLocale
import java.time.LocalDate
import java.time.YearMonth
@Composable
fun VerticalMonthCalendarScreen() {
val currentMonth = remember { YearMonth.now() }
val state = rememberCalendarState(
startMonth = currentMonth.minusMonths(6),
endMonth = currentMonth.plusMonths(6),
firstVisibleMonth = currentMonth,
firstDayOfWeek = firstDayOfWeekFromLocale(),
)
VerticalCalendar(
state = state,
calendarScrollPaged = false, // free-form scroll
dayContent = { day ->
Box(
Modifier
.aspectRatio(1f)
.padding(2.dp)
.clip(CircleShape)
.background(if (day.date == LocalDate.now()) Color.Blue else Color.Transparent),
contentAlignment = Alignment.Center,
) {
Text(
day.date.dayOfMonth.toString(),
color = if (day.date == LocalDate.now()) Color.White else Color.Black,
)
}
},
monthHeader = { month ->
Text(
"${month.yearMonth.month} ${month.yearMonth.year}",
Modifier.padding(vertical = 8.dp, horizontal = 16.dp),
style = MaterialTheme.typography.headlineSmall,
)
},
)
}
```
--------------------------------
### Bind Month Header Data with Kotlin
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Implement the `MonthHeaderFooterBinder` to create a `ViewContainer` for the month header and bind data to it. This example shows how to set the short display names for the days of the week.
```kotlin
class MonthViewContainer(view: View) : ViewContainer(view) {
// Alternatively, you can add an ID to the container layout and use findViewById()
val titlesContainer = view as ViewGroup
}
calendarView.monthHeaderBinder = object : MonthHeaderFooterBinder {
override fun create(view: View) = MonthViewContainer(view)
override fun bind(container: MonthViewContainer, data: CalendarMonth) {
// Remember that the header is reused so this will be called for each month.
// However, the first day of the week will not change so no need to bind
// the same view every time it is reused.
if (container.titlesContainer.tag == null) {
container.titlesContainer.tag = data.yearMonth
container.titlesContainer.children.map { it as TextView }
.forEachIndexed {
index,
textView ->
val dayOfWeek = daysOfWeek[index]
val title = dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.getDefault())
textView.text = title
// In the code above, we use the same `daysOfWeek` list
// that was created when we set up the calendar.
// However, we can also get the `daysOfWeek` list from the month data:
// val daysOfWeek = data.weekDays.first().map { it.date.dayOfWeek }
// Alternatively, you can get the value for this specific index:
// val dayOfWeek = data.weekDays.first()[index].date.dayOfWeek
}
}
}
}
```
--------------------------------
### Get Days of Week
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Generates a list of `DayOfWeek` based on the user's current locale. This is useful for displaying weekday titles.
```kotlin
val daysOfWeek = daysOfWeek() // Available in the library
```
--------------------------------
### Basic Week Calendar Implementation in Compose
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Shows the basic structure for implementing a `WeekCalendar` composable. It requires a `WeekCalendarState` and a `dayContent` lambda for rendering each day.
```kotlin
@Composable
fun MainScreen() {
val state = rememberWeekCalendarState(
startDate = ...,
endDate = ...,
firstVisibleWeekDate = ...,
firstDayOfWeek = ...
)
WeekCalendar(
state = state,
dayContent = { Day(it) }
)
}
```
--------------------------------
### Basic HeatMap Calendar Implementation in Compose
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Demonstrates the basic usage of the `HeatMapCalendar` composable. It requires a `HeatMapCalendarState` and provides slots for `dayContent`, `weekHeader`, and `monthHeader`.
```kotlin
@Composable
fun MainScreen() {
val currentMonth = remember { YearMonth.now() }
val startMonth = remember { currentMonth.minusMonths(100) } // Adjust as needed
val endMonth = remember { currentMonth.plusMonths(100) } // Adjust as needed
val firstDayOfWeek = remember { firstDayOfWeekFromLocale() } // Available from the library
val state = rememberHeatMapCalendarState(
startMonth = startMonth,
endMonth = startMonth,
firstVisibleMonth = currentMonth,
firstDayOfWeek = firstDayOfWeek,
)
HeatMapCalendar(
state = state,
dayContent = { day, _ -> Day(day) },
weekHeader = { WeekHeader(it) },
monthHeader = { MonthHeader(it) }
)
}
```
--------------------------------
### Implement Date Selection with Background
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Customize the `Day` composable to display a background when a date is selected. This involves modifying the `Box` background based on an `isSelected` state.
```kotlin
@Composable
fun Day(day: CalendarDay, isSelected: Boolean, onClick: (CalendarDay) -> Unit) {
Box(
modifier = Modifier
.aspectRatio(1f)
.clip(CircleShape)
.background(color = if (isSelected) Color.Green else Color.Transparent)
.clickable(
enabled = day.position == DayPosition.MonthDate,
onClick = { onClick(day) }
),
contentAlignment = Alignment.Center
) {
Text(text = day.date.dayOfMonth.toString())
}
}
```
--------------------------------
### Create a Contribution Heatmap Calendar
Source: https://context7.com/kizitonwose/calendar/llms.txt
Use HeatMapCalendar to visualize frequency data over time, similar to a GitHub contribution chart. Configure month and week headers, and customize day content appearance based on data values.
```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.kizitonwose.calendar.compose.HeatMapCalendar
import com.kizitonwose.calendar.compose.HeatMapWeekHeaderPosition
import com.kizitonwose.calendar.compose.rememberHeatMapCalendarState
import java.time.DayOfWeek
import java.time.LocalDate
import java.time.YearMonth
import java.time.format.TextStyle
import java.util.Locale
@Composable
fun ContributionCalendar(contributions: Map) {
val currentMonth = remember { YearMonth.now() }
val startMonth = remember { currentMonth.minusMonths(11) }
val state = rememberHeatMapCalendarState(
startMonth = startMonth,
endMonth = currentMonth,
firstVisibleMonth = currentMonth,
firstDayOfWeek = DayOfWeek.SUNDAY,
)
HeatMapCalendar(
state = state,
weekHeaderPosition = HeatMapWeekHeaderPosition.Start,
dayContent = { day, _ ->
val count = contributions[day.date] ?: 0
val alpha = (count.coerceAtMost(10) / 10f).coerceAtLeast(0.05f)
Box(
Modifier
.aspectRatio(1f)
.padding(2.dp)
.clip(RoundedCornerShape(3.dp))
.background(Color(0xFF216E39).copy(alpha = alpha)),
)
},
weekHeader = { dayOfWeek ->
// Render Mon / Wed / Fri row labels
if (dayOfWeek == DayOfWeek.MONDAY || dayOfWeek == DayOfWeek.WEDNESDAY || dayOfWeek == DayOfWeek.FRIDAY) {
Text(
dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.getDefault()),
Modifier.padding(end = 4.dp),
style = MaterialTheme.typography.labelSmall,
)
} else {
Spacer(Modifier.padding(end = 4.dp))
}
},
monthHeader = { month ->
Text(
month.yearMonth.month.getDisplayName(TextStyle.SHORT, Locale.getDefault()),
Modifier.padding(bottom = 4.dp),
style = MaterialTheme.typography.labelSmall,
)
},
)
}
```
--------------------------------
### Conditional Month Visibility in Year Calendar
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Shows how to control which months are visible within the year calendar grid using the `isMonthVisible` parameter. This example only displays months from October 2024 onwards.
```kotlin
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.kizitonwose.calendar.core.Year
import com.kizitonwose.calendar.core.firstDayOfWeekFromLocale
import com.kizitonwose.calendar.core.YearMonth
import com.kizitonwose.calendar.core.Month
import com.kizitonwose.calendar.yearcalendar.HorizontalYearCalendar
import com.kizitonwose.calendar.yearcalendar.rememberYearCalendarState
@Composable
fun MainScreen() {
val october2024 = remember { YearMonth.of(2024, Month.OCTOBER) }
val startYear = remember { Year.of(2024) }
val endYear = remember { Year.of(2054) }
val firstDayOfWeek = remember { firstDayOfWeekFromLocale() }
val state = rememberYearCalendarState(
startYear = startYear,
endYear = endYear,
firstVisibleYear = startYear,
firstDayOfWeek = firstDayOfWeek,
)
HorizontalYearCalendar(
state = state,
dayContent = { Day(it) },
yearHeader = { YearHeader(it) },
monthHeader = { MonthHeader(it) },
isMonthVisible = { data ->
data.yearMonth >= october2024
}
)
}
```
--------------------------------
### Initialize Calendar State with First Day of Week
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Configures the `rememberCalendarState` with the first day of the week derived from the `daysOfWeek` list. This ensures the calendar's first day aligns with user expectations.
```kotlin
val firstDayOfWeek = remember { firstDayOfWeekFromLocale() }
val daysOfWeek = remember { daysOfWeek() }
val state = rememberCalendarState(
startMonth = startMonth,
endMonth = endMonth,
firstVisibleMonth = currentMonth,
firstDayOfWeek = daysOfWeek.first()
)
```
--------------------------------
### Bind Month Dates and Handle Clicks
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Implement the MonthDayBinder to create date cell views and set up click listeners. This is where you bind data to your custom view container.
```kotlin
calendarView.dayBinder = object : MonthDayBinder {
override fun create(view: View) = DayViewContainer(view)
override fun bind(container: DayViewContainer, data: CalendarDay) {
// Set the calendar day for this container.
container.day = data
// Set the date text
container.textView.text = data.date.dayOfMonth.toString()
// Any other binding logic
}
}
```
--------------------------------
### Create a Custom View Container for Dates
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
A Kotlin class to hold references to the views within a date cell and store the associated CalendarDay.
```kotlin
class DayViewContainer(view: View) : ViewContainer(view) {
val textView = view.findViewById(R.id.calendarDayText)
// Will be set when this container is bound
lateinit var day: CalendarDay
init {
view.setOnClickListener {
// Use the CalendarDay associated with this container.
}
}
}
```
--------------------------------
### Custom Day Composable with Fixed Height
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
An alternative `Day` composable demonstrating how to set a specific height for calendar cells, such as `Modifier.height(70.dp)`, instead of relying on aspect ratio.
```kotlin
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.foundation.layout.height
import androidx.compose.ui.unit.dp
import com.kizitonwose.calendar.core.CalendarDay
@Composable
fun Day(day: CalendarDay) {
Box(
modifier = Modifier.height(70.dp), // Example of setting a specific height
contentAlignment = Alignment.Center
) {
Text(text = day.date.dayOfMonth.toString())
}
}
```
--------------------------------
### Create DayViewContainer for Date Cells
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Implement a `ViewContainer` to hold references to the views within your custom day layout. This allows for efficient view recycling.
```kotlin
class DayViewContainer(view: View) : ViewContainer(view) {
val textView = view.findViewById(R.id.calendarDayText)
// With ViewBinding
// val textView = CalendarDayLayoutBinding.bind(view).calendarDayText
}
```
--------------------------------
### Implement MonthDayBinder for CalendarView
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Provide a `MonthDayBinder` to the `CalendarView` to define how each date cell is populated. This involves creating a `DayViewContainer` and binding data to it.
```kotlin
calendarView.dayBinder = object : MonthDayBinder {
// Called only when a new container is needed.
override fun create(view: View) = DayViewContainer(view)
// Called every time we need to reuse a container.
override fun bind(container: DayViewContainer, data: CalendarDay) {
container.textView.text = data.date.dayOfMonth.toString()
}
}
```
--------------------------------
### daysOfWeek / firstDayOfWeekFromLocale
Source: https://context7.com/kizitonwose/calendar/llms.txt
Utilities for obtaining locale-aware lists of days of the week.
```APIDOC
## daysOfWeek / firstDayOfWeekFromLocale
### Description
These functions provide locale-aware lists of `DayOfWeek` values, useful for initializing calendar states and rendering week headers.
### Methods
- `daysOfWeek()`: Returns a list of 7 `DayOfWeek` values starting from the locale's default first day (e.g., Sunday for en-US, Monday for many European locales).
- `daysOfWeek(firstDayOfWeek: DayOfWeek)`: Returns a list of 7 `DayOfWeek` values starting from the specified `firstDayOfWeek`.
- `firstDayOfWeekFromLocale()`: A shortcut function that returns the first day of the week according to the current locale. This is equivalent to calling `daysOfWeek().first()`.
```
--------------------------------
### CalendarView Methods
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Methods for interacting with the CalendarView, including scrolling, notifications, and finding visible elements.
```APIDOC
## CalendarView
### Methods
- **`scrollToDate(date: LocalDate)`**
Scroll to a specific date on the calendar.
- **`smoothScrollToDate(date: LocalDate)`**
Scroll smoothly to a specific date on the calendar.
- **`scrollToMonth(month: YearMonth)`**
Scroll to a month on the calendar.
- **`smoothScrollToMonth(month: YearMonth)`**
Scroll smoothly to a month on the calendar.
- **`notifyDateChanged(date: LocalDate)`**
Reload the view for the specified date.
- **`notifyMonthChanged(month: YearMonth)`**
Reload the header, body and footer views for the specified month.
- **`notifyCalendarChanged()`**
Reload the entire calendar.
- **`findFirstVisibleMonth()`**
Find the first visible month on the calendar.
- **`findLastVisibleMonth()`**
Find the last visible month on the calendar.
- **`findFirstVisibleDay()`**
Find the first visible day on the calendar.
- **`findLastVisibleDay()`**
Find the last visible day on the calendar.
- **`updateMonthData()`**
Update the calendar's start month or end month or the first day of week after the initial setup. The currently visible month is preserved.
```
--------------------------------
### Implement Single and Range Date Selection in Compose Calendar
Source: https://context7.com/kizitonwose/calendar/llms.txt
Manages selected dates and date ranges by updating state variables. Handles click events to toggle single selection or set range start/end dates.
```kotlin
@Composable
fun SingleAndRangeSelectionCalendar() {
val currentMonth = remember { YearMonth.now() }
val state = rememberCalendarState(
startMonth = currentMonth.minusMonths(12),
endMonth = currentMonth.plusMonths(12),
firstVisibleMonth = currentMonth,
firstDayOfWeek = firstDayOfWeekFromLocale(),
)
// --- Single selection ---
var selectedDate by remember { mutableStateOf(null) }
// --- Range selection ---
var rangeStart by remember { mutableStateOf(null) }
var rangeEnd by remember { mutableStateOf(null) }
fun isInRange(date: LocalDate): Boolean {
val s = rangeStart ?: return false
val e = rangeEnd ?: return false
return date in s..e
}
HorizontalCalendar(
state = state,
dayContent = { day ->
if (day.position != DayPosition.MonthDate) {
Box(Modifier.aspectRatio(1f)) // invisible placeholder
return@HorizontalCalendar
}
val inRange = isInRange(day.date)
val isStart = day.date == rangeStart
val isEnd = day.date == rangeEnd
val isSelected = day.date == selectedDate
Box(
modifier = Modifier
.aspectRatio(1f)
.padding(2.dp)
.clip(
when {
isStart || isEnd -> CircleShape
inRange -> RoundedCornerShape(0)
else -> CircleShape
}
)
.background(
when {
isStart || isEnd -> Color(0xFF4CAF50)
inRange -> Color(0xFFC8E6C9)
isSelected -> Color(0xFF2196F3)
else -> Color.Transparent
}
)
.clickable {
// Toggle single selection
selectedDate = if (selectedDate == day.date) null else day.date
// Range selection: first click sets start, second sets end
when {
rangeStart == null -> rangeStart = day.date
rangeEnd == null && day.date >= rangeStart!! -> rangeEnd = day.date
else -> { rangeStart = day.date; rangeEnd = null }
}
},
contentAlignment = Alignment.Center,
) {
Text(
day.date.dayOfMonth.toString(),
color = if (isStart || isEnd || isSelected) Color.White else Color.Black,
)
}
},
)
}
```
--------------------------------
### Derive Days of Week from Month Data for Month Header
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
An alternative method to obtain the `daysOfWeek` list directly from the `month` data passed into the `monthHeader` lambda. This approach is useful if the `daysOfWeek` list is not readily available or needs to be context-specific.
```kotlin
@Composable
fun MainScreen() {
HorizontalCalendar(
state = state,
dayContent = { Day(it) },
monthHeader = { month ->
// You may want to use `remember {}` here so the mapping is not done
// every time as the days of week order will never change unless
// you set a new value for `firstDayOfWeek` in the state.
val daysOfWeek = month.weekDays.first().map { it.date.dayOfWeek }
MonthHeader(daysOfWeek = daysOfWeek)
}
)
}
```
--------------------------------
### Configure CalendarView with Custom Date Layout
Source: https://github.com/kizitonwose/calendar/blob/main/docs/View.md
Set the custom date cell layout resource for the CalendarView in XML.
```xml
```
--------------------------------
### Gradle Dependency for Compose Multiplatform Project
Source: https://context7.com/kizitonwose/calendar/llms.txt
Include the compose-multiplatform artifact in your shared module's build.gradle.kts for cross-platform compatibility.
```kotlin
kotlin {
sourceSets {
commonMain.dependencies {
implementation("com.kizitonwose.calendar:compose-multiplatform:2.6.0")
}
}
}
```
--------------------------------
### Add Compose Multiplatform Calendar Library
Source: https://github.com/kizitonwose/calendar/blob/main/README.md
Add the multiplatform calendar library to your project's build.gradle.kts in the commonMain source set for Compose Multiplatform projects. This supports Android, iOS, js, WasmJs, and Desktop platforms.
```kotlin
commonMain.dependencies {
// The calendar library for compose multiplatform projects
// Supports Android, iOS, js, WasmJs and Desktop platforms
implementation("com.kizitonwose.calendar:compose-multiplatform:")
}
```
--------------------------------
### Customize Month Appearance with Background and Borders in Compose Calendar
Source: https://context7.com/kizitonwose/calendar/llms.txt
Applies custom styling to the month's background using a gradient and wraps the month container with borders and rounded corners. Adjusts month width relative to screen size.
```kotlin
@Composable
fun StyledMonthCalendar() {
val state = rememberCalendarState(
startMonth = YearMonth.now().minusMonths(6),
endMonth = YearMonth.now().plusMonths(6),
firstVisibleMonth = YearMonth.now(),
firstDayOfWeek = DayOfWeek.SUNDAY,
)
HorizontalCalendar(
state = state,
// Gradient behind the day grid
monthBody = { _, content ->
Box(
Modifier.background(
Brush.verticalGradient(listOf(Color(0xFFE3F2FD), Color(0xFFBBDEFB)))
)
) { content() }
},
// Rounded bordered month card, narrower than screen
monthContainer = { _, container ->
val screenWidth = LocalConfiguration.current.screenWidthDp.dp
Box(
Modifier
.width(screenWidth * 0.85f)
.padding(8.dp)
.clip(RoundedCornerShape(12.dp))
.border(1.dp, Color(0xFF1976D2), RoundedCornerShape(12.dp))
) { container() }
},
dayContent = { day ->
Box(Modifier.aspectRatio(1f), Alignment.Center) {
Text(
day.date.dayOfMonth.toString(),
color = if (day.position == DayPosition.MonthDate) Color.Black else Color.Gray,
)
}
},
)
}
```
--------------------------------
### Integrate Static Days of Week Title with Calendar
Source: https://github.com/kizitonwose/calendar/blob/main/docs/Compose.md
Shows how to use the `DaysOfWeekTitle` composable above the `HorizontalCalendar` within a `Column`. This provides a static header for the weekdays.
```kotlin
@Composable
fun MainScreen() {
Column {
DaysOfWeekTitle(daysOfWeek = daysOfWeek) // Use the title here
HorizontalCalendar(
state = state,
dayContent = { Day(it) }
)
}
}
```
--------------------------------
### Display a Full Year Grid Calendar
Source: https://context7.com/kizitonwose/calendar/llms.txt
Use HorizontalYearCalendar or VerticalYearCalendar to show all months of a year in a grid, suitable for large screens. Customize the layout, visibility of months, and appearance of day and header cells.
```kotlin
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.kizitonwose.calendar.compose.HorizontalYearCalendar
import com.kizitonwose.calendar.compose.rememberYearCalendarState
import com.kizitonwose.calendar.core.DayPosition
import com.kizitonwose.calendar.core.OutDateStyle
import java.time.Month
import java.time.Year
import java.time.format.TextStyle
import java.util.Locale
@Composable
fun YearCalendarScreen() {
val currentYear = remember { Year.now() }
val state = rememberYearCalendarState(
startYear = currentYear.minusYears(2),
endYear = currentYear.plusYears(2),
firstVisibleYear = currentYear,
firstDayOfWeek = firstDayOfWeekFromLocale(),
outDateStyle = OutDateStyle.EndOfRow,
)
// Only show months from October 2024 onward (for a fiscal year calendar)
val october2024 = remember { YearMonth.of(2024, Month.OCTOBER) }
HorizontalYearCalendar(
state = state,
monthColumns = 3, // 3-column grid per year
monthHorizontalSpacing = 8.dp,
monthVerticalSpacing = 8.dp,
isMonthVisible = { data -> data.yearMonth >= october2024 },
dayContent = { day ->
Box(
Modifier
.aspectRatio(1f)
.padding(1.dp),
contentAlignment = Alignment.Center,
) {
Text(
day.date.dayOfMonth.toString(),
style = MaterialTheme.typography.labelSmall,
color = if (day.position == DayPosition.MonthDate) Color.Black else Color.LightGray,
)
}
},
monthHeader = { month ->
Text(
month.yearMonth.month.getDisplayName(TextStyle.SHORT, Locale.getDefault()),
Modifier.padding(4.dp),
style = MaterialTheme.typography.labelMedium,
)
},
yearHeader = { year ->
Text(
year.year.toString(),
Modifier.padding(8.dp),
style = MaterialTheme.typography.headlineMedium,
)
},
)
}
```