From ce6da44c5253b3d84d8f15723df0adae8ecf3f8b Mon Sep 17 00:00:00 2001 From: xfy Date: Fri, 15 May 2026 10:08:25 +0800 Subject: [PATCH] Fix swipe interpolation discontinuity and remove debug println Use currentPage instead of settledPage for interpolatedWeeks calculation to prevent gridH jumps during month transitions. When offsetFraction is near zero, compute weeks from currentPage rather than stale callback state. Remove all debug println statements and TAG constants. Co-Authored-By: Claude Opus 4.7 --- .../plus/rua/project/CalendarViewModel.kt | 6 ++-- .../kotlin/plus/rua/project/ui/BottomCard.kt | 16 +++++++--- .../plus/rua/project/ui/CalendarMonthPage.kt | 8 ++--- .../plus/rua/project/ui/CalendarMonthView.kt | 29 ++++++++----------- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/shared/src/commonMain/kotlin/plus/rua/project/CalendarViewModel.kt b/shared/src/commonMain/kotlin/plus/rua/project/CalendarViewModel.kt index e2c342d..0930b69 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/CalendarViewModel.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/CalendarViewModel.kt @@ -59,7 +59,8 @@ class CalendarViewModel(private val coroutineScope: CoroutineScope) { // 拖拽超过 50% 时自动折叠到周视图,否则回弹到月视图 fun onDragEnd() { coroutineScope.launch { - if (_collapseAnimatable.value > 0.5f) { + val current = _collapseAnimatable.value + if (current > 0.5f) { _collapseAnimatable.animateTo( targetValue = 1f, animationSpec = spring(dampingRatio = 0.8f, stiffness = 400f) @@ -85,7 +86,8 @@ class CalendarViewModel(private val coroutineScope: CoroutineScope) { // 下拉超过 50% 时自动展开到月视图,否则回弹到周视图 fun onExpandDragEnd() { coroutineScope.launch { - if (_collapseAnimatable.value < 0.5f) { + val current = _collapseAnimatable.value + if (current < 0.5f) { _collapseAnimatable.animateTo( targetValue = 0f, animationSpec = spring(dampingRatio = 0.8f, stiffness = 400f) diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/BottomCard.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/BottomCard.kt index 61e7c27..12111fb 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/BottomCard.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/BottomCard.kt @@ -41,8 +41,12 @@ fun BottomCard( if (viewModel.isCollapsed) { // 折叠状态:下拉恢复到月视图 detectVerticalDragGestures( - onDragEnd = { viewModel.onExpandDragEnd() }, - onDragCancel = { viewModel.onExpandDragEnd() } + onDragEnd = { + viewModel.onExpandDragEnd() + }, + onDragCancel = { + viewModel.onExpandDragEnd() + } ) { _, dragAmount -> val delta = -dragAmount / dragRange viewModel.onExpandDrag(delta) @@ -50,8 +54,12 @@ fun BottomCard( } else { // 展开状态:上拉折叠到周视图 detectVerticalDragGestures( - onDragEnd = { viewModel.onDragEnd() }, - onDragCancel = { viewModel.onDragEnd() } + onDragEnd = { + viewModel.onDragEnd() + }, + onDragCancel = { + viewModel.onDragEnd() + } ) { _, dragAmount -> val delta = -dragAmount / dragRange viewModel.onDrag(delta) diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthPage.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthPage.kt index 1b58061..7d59351 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthPage.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthPage.kt @@ -19,8 +19,6 @@ import kotlinx.datetime.LocalDate import kotlinx.datetime.minus import kotlinx.datetime.plus -private const val TAG = "CalMonthPage" - /** * 月度日历网格页面,支持折叠动画。 * @@ -59,11 +57,8 @@ fun CalendarMonthPage( val totalHeightDp = if (rowHeightPx > 0) { val p = collapseProgress val totalPx = H * (1 + (effectiveWeeks - 1) * (1f - p)) - println("[$TAG] year=$year month=$month rowH=$rowHeightPx H=$H effWeeks=$effectiveWeeks " + - "weeks.size=${weeks.size} p=$p totalPx=$totalPx selWeek=$selectedWeekIndex") with(density) { totalPx.toDp() } } else { - println("[$TAG] year=$year month=$month rowH=0 (not yet measured)") null } @@ -98,7 +93,8 @@ fun CalendarMonthPage( } with(density) { yPx.toDp() } } else if (rowHeightPx > 0) { - with(density) { (weekIndex * H).toDp() } + val yPx = weekIndex * H + with(density) { yPx.toDp() } } else { 0.dp } diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthView.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthView.kt index 4b0ef33..986f352 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthView.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthView.kt @@ -32,7 +32,6 @@ import plus.rua.project.CalendarViewModel private const val START_PAGE = Int.MAX_VALUE / 2 private const val ROW_PADDING_DP = 4 -private const val TAG = "CalMonthView" /** * 日历主界面,包含月/周视图切换和折叠动画。 @@ -68,21 +67,23 @@ fun CalendarMonthView( val rowPaddingPx = with(density) { ROW_PADDING_DP.dp.toPx() }.toInt() // 滑动偏移插值行数 - // 始终以 settledPage 为锚点,currentPage - settledPage 确定方向(-1/0/+1), - // abs(offsetFraction) 为过渡进度。 - // 这样在 currentPage 跳变前后,方向和进度都是连续的: - // 跳变前: sp=8月, cp=8月, diff=0, offsetFraction>0 → 目标9月, fraction 0→0.5 - // 跳变后: sp=8月, cp=9月, diff=+1 → 目标9月, fraction 0.5→0 + // 以 currentPage 为基准页,offsetFraction 表示基准页与可视区域左边缘的偏移: + // offsetFraction > 0:基准页偏右,可视区域露出下一页(page+1) + // offsetFraction < 0:基准页偏左,可视区域露出上一页(page-1) + // 过渡进度 = abs(offsetFraction),目标页 = page ± 1。 + // 当 currentPage 跳变(如从 Jul 跳到 Aug),基准页行数也随之跳变, + // 但 abs(offsetFraction) 同时从 ~0.5 降到 ~0.5(连续),所以插值结果连续: + // 跳变前: cp=Jul(5行), off=+0.49 → base=5, target=Aug(6), lerp(5,6,0.49)=5.49 + // 跳变后: cp=Aug(6行), off=-0.47 → base=6, target=Jul(5), lerp(6,5,0.47)=5.47 ← 连续! val offsetFraction by remember { derivedStateOf { pagerState.currentPageOffsetFraction } } val interpolatedWeeks = if (abs(offsetFraction) > 0.01f) { - val sp = pagerState.settledPage - val diff = pagerState.currentPage - sp // -1, 0, or +1 - val targetPage = if (diff != 0) sp + diff else sp + if (offsetFraction > 0) 1 else -1 - val baseWeeks = calculateWeeksCountForPage(sp, today) + val cp = pagerState.currentPage + val baseWeeks = calculateWeeksCountForPage(cp, today) + val targetPage = cp + if (offsetFraction > 0) 1 else -1 val targetWeeks = calculateWeeksCountForPage(targetPage, today) lerp(baseWeeks.toFloat(), targetWeeks.toFloat(), abs(offsetFraction)) } else { - currentWeeksCount.toFloat() + calculateWeeksCountForPage(pagerState.currentPage, today).toFloat() } // 预估行高:DayCell aspectRatio=1,宽度 = (screenWidth - horizontalPadding) / 7 @@ -111,12 +112,6 @@ fun CalendarMonthView( val calendarAreaHeightPx = headerHeightPx + gridHeightPx + rowPaddingPx val cardHeightPx = if (screenHeightPx > 0 && calendarAreaHeightPx > 0) screenHeightPx - calendarAreaHeightPx else 0 - println("[$TAG] p=$p rowH=$rowHeightPx estRowH=$estimatedRowHeightPx effRowH=$effectiveRowHeightPx " + - "headerH=$headerHeightPx gridH=$gridHeightPx calAreaH=$calendarAreaHeightPx " + - "screenH=$screenHeightPx cardH=$cardHeightPx " + - "currentWeeks=$currentWeeksCount interpolatedWeeks=$interpolatedWeeks effectiveWeeks=$effectiveWeeks " + - "offsetFraction=$offsetFraction currentPage=${pagerState.currentPage} settledPage=${pagerState.settledPage}") - // 当 rowHeightPx 已知时,用计算的高度约束 pager;否则让 pager 自由扩展以测量行高 val pagerModifier = if (rowHeightPx > 0 && gridHeightPx > 0) { Modifier