From 7e2bb048f605d4a64464321ba3694642038fd4b7 Mon Sep 17 00:00:00 2001 From: xfy Date: Fri, 15 May 2026 00:17:00 +0800 Subject: [PATCH] Unify row height source in CalendarMonthPage Replace internal rowHeightPx measurement with external rowHeightPx parameter passed from CalendarMonthView. This eliminates the mismatch between outer gridHeightPx (based on shrinking container) and inner totalHeightDp (based on independently measured row height), which was causing visual jitter during collapse animation. Remove onRowHeightMeasured callback, TAG constant, and debug printlns from CalendarMonthPage as part of this refactor. Co-Authored-By: Claude Opus 4.7 --- .../plus/rua/project/ui/CalendarMonthPage.kt | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) 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 ca8d20e..989e4d4 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthPage.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthPage.kt @@ -7,13 +7,9 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds -import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex @@ -22,6 +18,14 @@ import kotlinx.datetime.LocalDate import kotlinx.datetime.minus import kotlinx.datetime.plus +/** + * 月度日历网格页面,支持折叠动画。 + * + * 折叠时非选中行高度按 (1-p) 缩放,选中行保持原始高度, + * 所有行通过手动 y-offset 定位,形成向选中行收缩的视觉效果。 + * + * @param rowHeightPx 从外层传入的锁定行高(像素),折叠过程中不变 + */ @Composable fun CalendarMonthPage( year: Int, @@ -30,7 +34,7 @@ fun CalendarMonthPage( today: LocalDate, onDateClick: (LocalDate) -> Unit, collapseProgress: Float, - onRowHeightMeasured: ((Int) -> Unit)? = null, + rowHeightPx: Int, modifier: Modifier = Modifier ) { val days = remember(year, month) { @@ -44,15 +48,11 @@ fun CalendarMonthPage( } val hasSelectedWeek = selectedWeekIndex >= 0 - - var rowHeightPx by remember { mutableIntStateOf(0) } - val rowMeasured = rowHeightPx > 0 val H = rowHeightPx.toFloat() - // 总高度 = 6行 × 行高(展开时),或选中行高度(折叠时) - val totalHeightDp = if (rowMeasured) { + // 总高度 = 选中行高度 + 上方行压缩高度 + 下方行压缩高度 + val totalHeightDp = if (rowHeightPx > 0) { if (hasSelectedWeek) { - // 选中行高度 + 上方行压缩高度 + 下方行压缩高度 val aboveH = selectedWeekIndex * H * (1f - collapseProgress) val belowH = (weeks.size - 1 - selectedWeekIndex) * H * (1f - collapseProgress) val selH = H @@ -78,16 +78,15 @@ fun CalendarMonthPage( else -> 1f } - val rowHeightDp = if (rowMeasured && rowScale > 0.01f) { + val rowHeightDp = if (rowHeightPx > 0 && rowScale > 0.01f) { with(density) { (H * rowScale).toDp() } - } else if (!rowMeasured) { + } else if (rowHeightPx <= 0) { null } else { 0.dp } - // 手动计算每行的视觉 y 位置 - val yOffsetDp = if (rowMeasured && hasSelectedWeek) { + val yOffsetDp = if (rowHeightPx > 0 && hasSelectedWeek) { val yPx = when { isAbove -> weekIndex * H * (1f - collapseProgress) isSelected -> selectedWeekIndex * H * (1f - collapseProgress) @@ -95,7 +94,7 @@ fun CalendarMonthPage( else -> weekIndex * H } with(density) { yPx.toDp() } - } else if (rowMeasured) { + } else if (rowHeightPx > 0) { with(density) { (weekIndex * H).toDp() } } else { 0.dp @@ -113,11 +112,6 @@ fun CalendarMonthPage( else Modifier ) .offset(y = yOffsetDp) - .onSizeChanged { size -> - if (size.height > 0 && !rowMeasured) { - rowHeightPx = size.height - } - } .padding(vertical = 4.dp) ) { week.forEach { dayData -> @@ -141,7 +135,7 @@ private data class DayData( val isCurrentMonth: Boolean ) -@Suppress("DEPRECATION") +@Suppress("DEPRECATION") // monthNumber 无替代 API,kotlinx-datetime 尚未提供新接口 private fun generateMonthDays(year: Int, month: Int): List { val firstOfMonth = LocalDate(year, month, 1) val offset = firstOfMonth.dayOfWeek.ordinal