Reputation: 4085
You style a CalendarView
like so:
AndroidView({
CalendarView(android.view.ContextThemeWrapper(it, R.style.CustomCalendar)).apply {
dateTextAppearance = R.style.CustomDate
weekDayTextAppearance = R.style.CustomWeek
}
})
<style name="CustomDay" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">@color/white</item>
</style>
<style name="CustomWeek" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">@color/white</item>
</style>
<style name="CustomCalendar" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
<item name="android:textColorPrimary">@color/teal_700</item>
<item name="colorAccent">@color/purple_200</item>
<item name="colorOnPrimary">@color/purple_200</item>
<item name="colorSurface">@color/purple_200</item>
</style>
CalendarView does not let you programmatically set its colours anymore. They must come from a XML style.
Is it possible to make the colours for CalendarView
come from the colours defined in Compose, rather than the colours defined in the XML?
Currently the duplication is vaguely manageable, except for the when the user changes to a dark mode Compose theme--then the CalendarView
's colours won't change to dark mode; the dark mode only exists within Compose world.
Note: Android interaction in Compose is excellent. Yet Android views that demand xml styles force a duplication of Compose and XML styles and colours, if you decide you want Compose to be source of truth, and you also want to use Android Views. And how they switch during theme change is a question I still haven't answered sufficiently.
Upvotes: 3
Views: 2697
Reputation: 363687
Is it possible to make the colours for CalendarView come from the colours defined in Compose, rather than the colours defined in the XML?
Short answer: no. From the doc:
Note: Ideally, there would be a way to define your theme and styling in Compose, and have it automatically reflected in the View system, but that's not possible due to the limitations of the view styling system.
The style and the colors used by the CalendarView
are defined in the code and it uses resources defined in the xml files. This means your app's theming will have 2 sources of truth: the View-based theme and the Compose theme.
To handle the dark mode just define the your themeoverlay and styles in the res/values-night
folder:
For example:
<style name="CustomDate" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">@color/red600</item>
</style>
<style name="CustomWeek" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">@color/red600Light</item>
</style>
<style name="CustomCalendar" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
<item name="android:textColorPrimary">@color/purple_700</item>
<item name="colorAccent">@color/teal_200</item>
<item name="colorOnPrimary">@color/teal_200</item>
<item name="colorSurface">@color/teal_200</item>
</style>
Dark mode:.
Upvotes: 1
Reputation: 4085
I'm guessing it's not possible to make Android XML style colours etc come from Compose.
But it is possible to make those XML styles changes when the Compose dark/light mode changes.
You check for a boolean that states if the user has chosen dark mode (I put it in my view model). And if so chose different XML style resources for that.
@Compose
fun AndroidCalendarView(
yourViewModel: YourViewModel = LocalViewModel.current
) {
var calTheme = R.style.CustomCalendar
var dateTheme = R.style.CustomDate
var weekTheme = R.style.CustomWeek
if (yourViewModel.darkTheme) {
calTheme = R.style.CustomCalendarDark
dateTheme = R.style.CustomDateDark
weekTheme = R.style.CustomDateWeek
}
AndroidView({
CalendarView(android.view.ContextThemeWrapper(it, calTheme)).apply {
dateTextAppearance = dateTheme
weekDayTextAppearance = weekTheme
}
})
}
This means your one theme xml style will have two sets of styles, one for light more and one for dark mode.
<style name="CustomDay" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">@color/black</item>
</style>
<style name="CustomWeek" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">@color/black</item>
</style>
<style name="CustomCalendar" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
<item name="android:textColorPrimary">@color/teal_700</item>
<item name="colorAccent">@color/purple_200</item>
<item name="colorOnPrimary">@color/purple_200</item>
<item name="colorSurface">@color/purple_200</item>
</style>
<style name="CustomDayDark" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">@color/white</item>
</style>
<style name="CustomWeekDark" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">@color/white</item>
</style>
<style name="CustomCalendarDark" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
<item name="android:textColorPrimary">@color/teal_700</item>
<item name="colorAccent">@color/purple_200</item>
<item name="colorOnPrimary">@color/purple_200</item>
<item name="colorSurface">@color/purple_200</item>
</style>
Hacky, but it works.
Upvotes: 2