Security News
Supply Chain Attack Detected in Solana's web3.js Library
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
io.github.boguszpawlowski.composecalendar:kotlinx-datetime
Advanced tools
A set of utilities supporting usage of kotlin datetime instead of java.time.
Compose Calendar is a composable handling all complexity of rendering calendar component and date selection. Due to flexibility provided by slot API's, you can decide how the calendar will look like, the library will handle proper calendar elements arrangement and it's state.
Library is available on Maven Central repository.
// module-level build.gradle
dependecies {
implementation "io.github.boguszpawlowski.composecalendar:composecalendar:<latest-version>"
// separate artifact with utilities for working with kotlinx-datetime
implementation "io.github.boguszpawlowski.composecalendar:kotlinx-datetime:<latest-version>"
}
Snapshots are available on Sonatype’s snapshots repository.
From version 1.3.0 library no longer uses coreLibraryDesugaring
itself. If you are using it in project supporting min SDK < 26, you need to add it to prevent runtime crashes.
// app-level build.gradle
android {
compileOptions {
coreLibraryDesugaringEnabled true
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.0.4"
}
To show the basic version of the calendar, without any kind of selection mechanism, you can simply use the StaticCalendar
composable without passing any parameters:
@Composable
fun MainScreen() {
StaticCalendar()
}
This chunk will render the calendar with default components for each day, and also month and week headers.
See the StaticCalendarSample
file for a full example. For showing a week calendar, you can similarly use StaticWeekCalendar
:
@Composable
fun MainScreen() {
StaticWeekCalendar()
}
:exclamation: By default, at first the calendar will show current month. If you want to start with some different date, you have to pass an
initialMonth
parameter to the initial state of the calendar. See Initial State section
Calendar with a mechanism for selection. The default implementation uses DynamicSelectionState
(see Dynamic Selection section) which allows to change SelectionMode
in the runtime.
@Composable
fun MainScreen() {
SelectableCalendar()
}
By the default, after changing the selection mode, selection is cleared.
See the SelectableCalendarSample
file for a full example. For showing a week calendar, you can similarly use SelectableWeekCalendar
:
@Composable
fun MainScreen() {
SelectableWeekCalendar()
}
See the WeekCalendarSample
file for a full example.
:exclamation: If you want to define your own selection behavior, please check out the Custom Selection section and/or
CustomSelectionSample
.
For the customization you should pass your own composable functions as day content, moth header etc.:
@Composable
fun MyDay(dayState: DayState) {
Text(dayState.date.dayOfMonth.toString())
}
@Composable
fun MainScreen() {
StaticCalendar(
dayContent = { dayState -> MyDay(dayState) }
)
}
The same you can do for every customizable element:
Box
, but can be any layout.The Calendar
composable accepts a Modifier
for simple customization of the overall appearance.
See the CustomComponentsSample
for a full example.
As the selection state is represented by an interface, you can provide your own implementation, to suit your use-case. E.g:
class MonthSelectionState(
initialSelection: YearMonth? = null,
) : SelectionState {
private var selection by mutableStateOf(initialSelection)
override fun isDateSelected(date: LocalDate): Boolean =
date.yearMonth == selection
override fun onDateSelected(date: LocalDate) {
selection = if (date.yearMonth == selection) null else date.yearMonth
}
}
To use the defined selection state, you have to pass it into a generic version of Calendar
composable.
This chunk is an implementation that will select all days in a clicked day's month. For a full example
please check out CustomSelectionSample
file.
Apart from rendering your own components inside the calendar, you can modify it by passing different properties.:
showAdjacentMonths
- whenever to render days from adjacent months. Defaults to true
.firstDayOfWeek
- you can pass the DayOfWeek
which you want you week to start with. It defaults to the first day of week of the Locale.default()
.horizontalScrollEnabled
- a Boolean flag which enables month to be changed by a horizontal swipe. Defaults to true
.minMonth
- a YearMonth
object representing the minimum month that can be shown in the calendar. By default there is no minimum month.maxMonth
- a YearMonth
object representing the maximum month that can be shown in the calendar. By default there is no maximum month.:exclamation: You cannot set
minMonth
to be lower thanmaxMonth
and vice versa. If you do so, the calendar state won't change.
Apart from this, Calendar
you can pass a Modifier
object like in any other composable.
Calendar composable holds its state as an CalendarState
object, which consists of 2 properties.
MonthState
- current value of the presented month.SelectionState
- current value of the selection.Both properties are represented by interfaces, so the default implementation can be overwritten if needed. The calendar state is leveraging Compose saving mechanism, so that the state will survive any configuration change, or the process death.
Initial state for the static calendar is provided by the rememberCalendarState()
function. If you need to change the initial conditions, you can pass the params to it:
@Composable
fun MainScreen() {
StaticCalendar(
calendarState = rememberCalendarState(
initialMonth = YearMonth.now().plusYears(1),
)
)
}
In case of the selectable calendar, the state has additional parameters, used to calculate the initial selection:
@Composable
fun MainScreen() {
SelectableCalendar(
calendarState = rememberSelectableCalendarState(
initialMonth = YearMonth.now().plusYears(1),
initialSelection = listOf(LocalDate.parse("20-01-2020")),
initialSelectionMode = SelectionMode.Period,
)
)
}
In case you need to react to the state changes, or change the state from the outside of the composable,
you need to hoist the state out of the Calendar
composable:
@Composable
fun MainScreen() {
val calendarState = rememberCalendarState()
StaticCalendar(calendarState = calendarState)
// now you can manipulate the state from scope of this composable
calendarState.monthState.currentMonth = YearMonth.of(2020, 5)
}
By default, the SelectableCalendar
is using a DynamicSelectionState
implementation of SelectionState
. The selection is kept as a list of LocalDate
objects. For a purpose of flexibility, DynamicSelectionState
allows for 4 different selection modes, each one varying how the selection is changing after interacting with the calendar. Furthermore, selection mode can be changed in the runtime, for some specific use-cases.
Selection modes are represented by SelectionMode
enum, with following values:
None
- no selection allowed - selection will always be an empty list.Single
- only single day is selectable - selection will contain one or zero days selected.Multiple
- a list of dates can be selected.Period
- selectable period - implemented by start
and end
dates. - selection will contain all dates between start and the end date.
This implementation of SelectionState also allows for handling side-effects and vetoing the state change via confirmSelectionChange
callback.Apart from the default calendar, there is also a week calendar, which shows a single week at a time. It can be used in the same way as the default calendar, and has the same customization options.
As the core of the library is built on java.time
library, on Android SDK < 26 it requires to use core libary desugaring to access it's API.
As a result it's features may be unavailable to some project built around different date-time libraries (e.g. kotlinx-datetime). Although the project wont be migrating from java.time
, as it's the best suited for it, there is a separate kotlinx-datetime
artifact for those who need to use the library from a codebase based on it. It doesn't consist of a separate version of ComposeCalendar
features, but offers a small bunch of utilities, that will enable you to create your own wrapper, as briefly presented in KotlinDateTimeSample
. If the provided functionality, doesn't match your use-case, please submit an issue.
Copyright 2022 Bogusz Pawłowski
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
FAQs
Unknown package
We found that io.github.boguszpawlowski.composecalendar:kotlinx-datetime demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.