Runtime error on HorizontalCalendarView in KMM
Closed this issue ยท 10 comments
I've recently added the library in a KMM project (0.0.8). I've defined the CalendarView, which works perfect and then I realised I need to be able to go next/previous month as well.
I've added the HorizontalCalendarView just like in your sample:
HorizontalCalendarView(startDate = state.selectedDate) { monthOffset ->
CalendarView(
modifier = Modifier.padding(horizontal = standardHorizontalPadding),
day = { calendarState ->
DayView(
date = calendarState.date,
isForAnotherMonth = calendarState.isForPreviousMonth || calendarState.isForNextMonth,
isCurrentSelection = calendarState.date == state.selectedDate,
isDotVisible = false,
onClick = {
sharedViewModel.onEvent(
ShopUiEvent.SelectedDateChanged(
calendarState.date
)
)
},
)
},
dayOfWeekLabel = { dayOfWeek ->
Text(
(RomanianDayOfWeek at dayOfWeek.ordinal)?.name?.substring(
IntRange(
0, 2
)
) ?: "",
fontSize = 12.sp,
textAlign = TextAlign.Center,
)
},
config = rememberCalendarState(
startDate = state.selectedDate,
monthOffset = monthOffset,
showNextMonthDays = true,
showPreviousMonthDays = true,
showHeader = false,
showWeekdays = true,
),
)
}
But I have this following error/crash:
FATAL EXCEPTION: main
Process: x.x, PID: 22821
java.lang.NoSuchMethodError: No static method HorizontalPager-xYaah8o(Landroidx/compose/foundation/pager/PagerState;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/foundation/pager/PageSize;IFLandroidx/compose/ui/Alignment$Vertical;Landroidx/compose/foundation/gestures/snapping/SnapFlingBehavior;ZZLkotlin/jvm/functions/Function1;Landroidx/compose/ui/input/nestedscroll/NestedScrollConnection;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;III)V in class Landroidx/compose/foundation/pager/PagerKt; or its super classes (declaration of 'androidx.compose.foundation.pager.PagerKt' appears in /data/app/x.x-QSFiiDGAZAKLV15zDGub2A==/base.apk)
at io.wojciechosak.calendar.view.HorizontalCalendarViewKt.HorizontalCalendarView(HorizontalCalendarView.kt:60)
at presentation.screens.shop.schedule_service.ScheduleServiceScreenKt$ScheduleServiceScreen$2.invoke(ScheduleServiceScreen.kt:91)
at presentation.screens.shop.schedule_service.ScheduleServiceScreenKt$ScheduleServiceScreen$2.invoke(ScheduleServiceScreen.kt:62)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at presentation.GeneralComposablesKt$ScaffoldWithTopBar$4.invoke(GeneralComposables.kt:268)
at presentation.GeneralComposablesKt$ScaffoldWithTopBar$4.invoke(GeneralComposables.kt:266)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:118)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.material3.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1$bodyContentPlaceables$1.invoke(Scaffold.kt:303)
at androidx.compose.material3.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1$bodyContentPlaceables$1.invoke(Scaffold.kt:285)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$subcompose$3$1$1.invoke(SubcomposeLayout.kt:995)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$subcompose$3$1$1.invoke(SubcomposeLayout.kt:478)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:109)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35)
at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:95)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3531)
at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3458)
at androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:743)
at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1112)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:3812)
at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release(Composer.kt:3812)
at androidx.compose.runtime.CompositionImpl.composeInitial(Composition.kt:649)
at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:635)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcomposeInto(SubcomposeLayout.kt:501)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:473)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:464)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose(SubcomposeLayout.kt:448)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$Scope.subcompose(SubcomposeLayout.kt:873)
at androidx.compose.material3.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1.invoke-0kLqBqw(Scaffold.kt:285)
at androidx.compose.material3.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1.invoke(Scaffold.kt:179)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:710)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:135)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:255)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:254)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:488)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:501)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:257)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1622)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:39)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:623)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:599)
at androidx.compose.foundation.layout.BoxMeasurePolicy.measure-3p2s80s(Box.kt:151)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:135)
at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:646)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:187)
at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:646)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:187)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:255)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:254)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:488)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:501)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:257)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1622)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:39)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:623)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:599)
at androidx.compose.animation.AnimatedEnterExitMeasurePolicy.measure-3p2s80s(AnimatedVisibility.kt:852)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:135)
at androidx.compose.animation.EnterExitTransitionModifierNode.measure-3p2s80s(EnterExitTransition.kt:1158)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:187)
at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:646)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:187)
at androidx.compose.animation.AnimatedContentKt$AnimatedContent$6$1$1$1.invoke-3p2s80s(AnimatedContent.kt:733)
at androidx.compose.animation.AnimatedContentKt$AnimatedContent$6$1$1$1.invoke(AnimatedContent.kt:732)
at androidx.compose.ui.layout.LayoutModifierImpl.measure-3p2s80s(LayoutModifier.kt:294)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:187)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:255)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:254)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:488)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:501)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:257)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1622)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:39)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:623)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:599)
at androidx.compose.animation.AnimatedContentMeasurePolicy.measure-3p2s80s(AnimatedContent.kt:787)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:135)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:255)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.kt:254)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2408)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:501)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:257)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1622)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:39)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:623)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release(LayoutNode.kt:1194)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release$default(LayoutNode.kt:1185)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:360)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:553)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded$default(MeasureAndLayoutDelegate.kt:521)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:381)
at androidx.compose.ui.platform.AndroidComposeView.measureAndLayout(AndroidComposeView.android.kt:1221)
at androidx.compose.ui.node.Owner.measureAndLayout$default(Owner.kt:241)
at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1474)
at android.view.View.draw(View.java:20376)
at android.view.View.updateDisplayListIfDirty(View.java:19318)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
at android.view.View.updateDisplayListIfDirty(View.java:19277)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
at android.view.View.updateDisplayListIfDirty(View.java:19277)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
at android.view.View.updateDisplayListIfDirty(View.java:19277)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4405)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4385)
at android.view.View.updateDisplayListIfDirty(View.java:19277)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:686)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:692)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:800)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:3496)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3283)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2818)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1780)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7827)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
at android.view.Choreographer.doCallbacks(Choreographer.java:723)
at android.view.Choreographer.doFrame(Choreographer.java:658)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Do you know what could go wrong here?
Initially, I wanted to use the CalendarView alone, and have my own header with left-right arrows so I can change the month in the view, but that doesn't work.
If you help me using only the calendarview, as I don't need the sliding animation, I just need to swap months in the calendarView.. that would be great! @WojciechOsak
Hey @s-septimiu, I can not reproduce it, but I've found similar issue in jetpack compose, could you try this: https://stackoverflow.com/questions/76865105/jetpack-compose-horizontalpager-exception in your project?
Anyway if you don't want to use swipe animation you can use pagerState like this:
val pagerState = rememberPagerState(
initialPage = 100000 / 2,
pageCount = { 100000 },
)
val scope = rememberCoroutineScope()
Column {
Row {
Button(onClick = {
scope.launch { pagerState.scrollToPage(pagerState.currentPage - 1) }
}) {
Text("LEFT")
}
Button(onClick = {
scope.launch {
pagerState.scrollToPage(pagerState.currentPage + 1)
}
}) {
Text("RIGHT")
}
}
HorizontalCalendarView(
startDate = LocalDate.today(),
pagerState = pagerState
) { monthOffset ->
CalendarView(
config = rememberCalendarState(
startDate = LocalDate.today(),
monthOffset = monthOffset,
showNextMonthDays = true,
showPreviousMonthDays = true,
showHeader = true,
showWeekdays = true,
),
)
}
}
To use it only with CalendarView you need something like this:
val config = rememberCalendarState(
startDate = LocalDate.today(),
monthOffset = 0,
showNextMonthDays = true,
showPreviousMonthDays = true,
showHeader = true,
showWeekdays = true,
)
Column {
Row {
Button(onClick = {
val currentConfig = config.value
config.value = config.value.copy(
monthYear = currentConfig.monthYear.toLocalDate()
.minus(1, DateTimeUnit.MONTH).toMonthYear()
)
}) {
Text("LEFT")
}
Button(onClick = {
val currentConfig = config.value
config.value = config.value.copy(
monthYear = currentConfig.monthYear.toLocalDate()
.plus(1, DateTimeUnit.MONTH).toMonthYear()
)
}) {
Text("RIGHT")
}
}
CalendarView(
config = config,
)
}
but it looks like I've made mistake in the code of CalendarView, and I should not use remember for yearMonth - I am sorry for that! So above example will not work without lib update / fork.
I got some bugs to fix and update compose and kotlin to 2.0, soooo I am going to release new version of the lib so you can use CalendarView without HorizontalCalendarView.
Changes merged here and will be released with 0.0.9
I agree with you that the remember made this impossible. Thanks a lot for the quick reply and fix, looking forward for the 0.0.9
@s-septimiu lib is released ๐
Try 0.0.9 (Compose 1.6.1) or lib 1.0.0 (it supports Compose 2.0.0).
I've updated to 0.0.9 and it's working now. Thanks, you can close the issue.
Awesome, thank you for update! :)
And if u migrate to Kotlin 2.0.0 you can use lib 1.0.0 ๐
@s-septimiu hey, update about "No static method HorizontalPager" issue, I think I have find the root of the problem, and fix will be delivered in next couple hours in 1.0.1 version, please try and let me know if it helps if u still got that error.
@WojciechOsak unfortunately I don't have kotlin 2+ in my project so 1.0.1 won't run... If I update and I still see that issue open I will give you an update.