A composable Calendar.
-
Add it in your root build.gradle at the end of repositories:
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() maven { url 'https://jitpack.io' } } }
-
Add the dependency
dependencies { implementation 'com.github.dyguests:LinCalendar:0.4.0' }
val state = rememberLinCalendarState()
LinCalendar(
state = state,
)
fun rememberLinCalendarState(
initialDate: LocalDate = LocalDate.now(),
startDate: LocalDate = LocalDate.of(1900, 1, 1),
endDate: LocalDate = LocalDate.of(2099, 12, 31),
initialDisplayMode: LinCalendar.DisplayMode = LinCalendar.DisplayMode.MONTHLY,
option: LinCalendar.Option = LinCalendarDefaults.option(),
): LinCalendarState
enum class DisplayMode {
MONTHLY,
WEEKLY, // todo impl
}
data class Option(
val headerHeight: Dp = 32.dp,
val rowHeight: Dp = 36.dp,
val firstDayOfWeek: DayOfWeek = DayOfWeek.MONDAY,
val weekDisplayMode: WeekDisplayMode = WeekDisplayMode.FIXED_HEIGHT,
val locale: Locale = Locale.getDefault(),
)
Consider of WeekDisplayMode
, the height of Calendar in different months may be different.
Therefore, you cannot set the height of Calendar directly, but use headerHeight
and rowHeight
.
enum class WeekDisplayMode {
// Fixed height, leaving the fifth week empty
FIXED_HEIGHT,
// Fixed height, equally dividing height by weeks
EQUAL_HEIGHT, // todo impl
// Dynamic height, adapting to the number of weeks in the month
DYNAMIC_HEIGHT // todo impl
}
Each part of LinCalendar is composable, so you can customize each part yourself.
LinCalendar
monthsField
monthFiled
weekHeaderField
dayHeaderField
weekField
dayField
Add a highlighted background to today's day of the calendar.
Step 1
Add LinCalendar
val state = rememberLinCalendarState()
LinCalendar(
state = state,
)
Step 2
If you look at the source code, you can see that the above code is equivalent to:
LinCalendar(
state = state,
monthsField = LinCalendarDefaults.monthsField(
state = state,
monthFiled = LinCalendarDefaults.monthField(
state = state,
),
),
)
...
equivalent to:
LinCalendar(
state = state,
monthsField = LinCalendarDefaults.monthsField(
state = state,
monthFiled = LinCalendarDefaults.monthField(
state = state,
weekField = LinCalendarDefaults.weekField(
state = state,
dayField = LinCalendarDefaults.dayField(
state = state,
)
),
),
),
)
To highlighted background to today's day, You need to custom dayField
, change code to this:
val dayField = LinCalendarDefaults.dayField(
state = state,
)
LinCalendar(
// ...
dayField = dayField
// ...
)
Now we focus on dayField
Step 3
Inline the function LinCalendarDefaults.dayField
.(You can also copy the source code of LinCalendarDefaults.dayField
)
val dayField: @Composable RowScope.(YearMonth, LocalDate) -> Unit = { yearMonth: YearMonth, localDate: LocalDate ->
val now = remember { LocalDate.now() }
Box(
modifier = Modifier
.height(state.option.rowHeight)
.weight(1f)
.then(Modifier),
contentAlignment = Alignment.Center,
) {
Text(
text = localDate.dayOfMonth.toString(),
style = TextStyle(
color = if (localDate == now) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.onSurface,
fontWeight = if (localDate == now) FontWeight.Bold
else if (yearMonth.month == localDate.month) FontWeight.Normal
else FontWeight.Light,
),
)
}
}
Now you can add a highlighted background to today.
val dayField: @Composable RowScope.(YearMonth, LocalDate) -> Unit = { yearMonth: YearMonth, localDate: LocalDate ->
// ...
Box(
// ...
) {
if (localDate == now) {
Box(
modifier = Modifier
.size(32.dp)
.background(Color.Red, CircleShape)
)
}
Text(
// ...
style = TextStyle(
color = if (localDate == now) Color.White
// ...
),
)
}
}
That's it.
- 隐藏无关细节。比如monthFiled中的计算逻辑