Add debug logging and fix gridHeightPx derivedStateOf state tracking

gridHeightPx changed from derivedStateOf to direct computation because
derivedStateOf cannot track non-State local variable changes, causing
gridHeightPx to not update when rowHeightPx transitions from 0 to measured value.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
xfy 2026-05-15 11:21:29 +08:00
parent ddc852a667
commit c74de5f151
4 changed files with 33 additions and 12 deletions

View File

@ -47,12 +47,14 @@ class CalendarViewModel(private val coroutineScope: CoroutineScope) {
val currentMonth: Int get() = selectedDate.month.number
fun selectDate(date: LocalDate) {
println("CalendarViewModel: selectDate $date (was $selectedDate)")
selectedDate = date
}
fun onDrag(delta: Float) {
coroutineScope.launch {
val new = (_collapseAnimatable.value + delta).coerceIn(0f, 1f)
println("CalendarViewModel: onDrag delta=$delta, progress=${_collapseAnimatable.value} -> $new")
_collapseAnimatable.snapTo(new)
}
}
@ -61,17 +63,20 @@ class CalendarViewModel(private val coroutineScope: CoroutineScope) {
fun onDragEnd() {
coroutineScope.launch {
val current = _collapseAnimatable.value
println("CalendarViewModel: onDragEnd current=$current, threshold=$COLLAPSE_THRESHOLD")
if (current > COLLAPSE_THRESHOLD) {
_collapseAnimatable.animateTo(
targetValue = 1f,
animationSpec = spring(dampingRatio = 0.8f, stiffness = 400f)
)
isCollapsed = true
println("CalendarViewModel: collapsed=true")
} else {
_collapseAnimatable.animateTo(
targetValue = 0f,
animationSpec = spring(dampingRatio = 0.8f, stiffness = 400f)
)
println("CalendarViewModel: snapped back to 0f")
}
}
}
@ -80,6 +85,7 @@ class CalendarViewModel(private val coroutineScope: CoroutineScope) {
fun onExpandDrag(delta: Float) {
coroutineScope.launch {
val new = (_collapseAnimatable.value + delta).coerceIn(0f, 1f)
println("CalendarViewModel: onExpandDrag delta=$delta, progress=${_collapseAnimatable.value} -> $new")
_collapseAnimatable.snapTo(new)
}
}
@ -88,17 +94,20 @@ class CalendarViewModel(private val coroutineScope: CoroutineScope) {
fun onExpandDragEnd() {
coroutineScope.launch {
val current = _collapseAnimatable.value
println("CalendarViewModel: onExpandDragEnd current=$current, threshold=$COLLAPSE_THRESHOLD")
if (current < COLLAPSE_THRESHOLD) {
_collapseAnimatable.animateTo(
targetValue = 0f,
animationSpec = spring(dampingRatio = 0.8f, stiffness = 400f)
)
isCollapsed = false
println("CalendarViewModel: expanded=false")
} else {
_collapseAnimatable.animateTo(
targetValue = 1f,
animationSpec = spring(dampingRatio = 0.8f, stiffness = 400f)
)
println("CalendarViewModel: snapped back to 1f")
}
}
}

View File

@ -33,6 +33,7 @@ fun BottomCard(
) {
val density = LocalDensity.current
val dragRange = with(density) { DRAG_RANGE_DP.dp.toPx() }
println("BottomCard: isCollapsed=${viewModel.isCollapsed}, dragRange=$dragRange, progress=${viewModel.collapseProgress}")
Surface(
modifier = modifier

View File

@ -115,7 +115,10 @@ fun CalendarMonthPage(
.then(
if (weekIndex == 0 && rowHeightPx == 0) {
Modifier.onSizeChanged { size ->
if (size.height > 0) onRowHeightMeasured?.invoke(size.height)
if (size.height > 0) {
println("CalendarMonthPage: measured rowHeight=${size.height}px, reporting to parent")
onRowHeightMeasured?.invoke(size.height)
}
}
} else Modifier
)

View File

@ -31,6 +31,8 @@ import kotlin.math.abs
import kotlin.time.Clock
import plus.rua.project.CalendarViewModel
private const val TAG = "CalendarMonthView"
/**
* 日历主界面包含月/周视图切换和折叠动画
*
@ -59,8 +61,10 @@ fun CalendarMonthView(
val pagerState = rememberPagerState(initialPage = START_PAGE, pageCount = { Int.MAX_VALUE })
val p = viewModel.collapseProgress
println("$TAG: collapseProgress=$p, isCollapsed=${viewModel.isCollapsed}")
val headerHeightPx = monthHeaderHeightPx + weekdayHeaderHeightPx
val rowPaddingPx = with(density) { ROW_PADDING_DP.dp.toPx() }.toInt()
println("$TAG: headerHeightPx=$headerHeightPx (month=$monthHeaderHeightPx, weekday=$weekdayHeaderHeightPx), rowPaddingPx=$rowPaddingPx")
val interpolatedWeeks by remember {
derivedStateOf {
@ -85,27 +89,28 @@ fun CalendarMonthView(
(cellWidth + rowPadding).toInt()
} else 0
println("$TAG: screenWidthPx=$screenWidthPx, screenHeightPx=$screenHeightPx, estimatedRowHeightPx=$estimatedRowHeightPx, measuredRowHeightPx=$rowHeightPx")
val effectiveRowHeightPx = if (rowHeightPx > 0) rowHeightPx else estimatedRowHeightPx
// 折叠时网格高度公式(与 CalendarMonthPage 一致):
// gridH = rowH × (1 + (weeks-1) × (1-p))
val effectiveWeeks = interpolatedWeeks
val gridHeightPx by remember {
derivedStateOf {
if (effectiveRowHeightPx > 0) {
val rowH = effectiveRowHeightPx.toFloat()
if (p > OFFSET_FRACTION_THRESHOLD) {
(rowH * (1 + (effectiveWeeks - 1) * (1f - p))).toInt()
} else {
(rowH * effectiveWeeks).toInt()
}
} else 0
// gridHeightPx 必须直接计算而非 derivedStateOf因为 effectiveRowHeightPx 依赖 rowHeightPx state
// derivedStateOf 无法追踪非 State 的局部变量变化,导致 rowHeightPx 从 0 变为测量值时 gridHeightPx 不更新
val gridHeightPx = if (effectiveRowHeightPx > 0) {
val rowH = effectiveRowHeightPx.toFloat()
if (p > OFFSET_FRACTION_THRESHOLD) {
(rowH * (1 + (effectiveWeeks - 1) * (1f - p))).toInt()
} else {
(rowH * effectiveWeeks).toInt()
}
}
} else 0
val calendarAreaHeightPx = headerHeightPx + gridHeightPx + rowPaddingPx
val cardHeightPx = if (screenHeightPx > 0 && calendarAreaHeightPx > 0) screenHeightPx - calendarAreaHeightPx else 0
println("$TAG: effectiveRowHeightPx=$effectiveRowHeightPx, effectiveWeeks=$effectiveWeeks, gridHeightPx=$gridHeightPx, calendarAreaHeightPx=$calendarAreaHeightPx, cardHeightPx=$cardHeightPx")
// 当 rowHeightPx 已知时,用计算的高度约束 pager否则让 pager 自由扩展以测量行高
val pagerModifier = if (rowHeightPx > 0 && gridHeightPx > 0) {
@ -141,6 +146,7 @@ fun CalendarMonthView(
)
// 完全折叠且无动画时显示 WeekPager否则显示 CalendarPager含下拉恢复过程
if (viewModel.isCollapsed && viewModel.collapseProgress >= 1f) {
println("$TAG: Showing WeekPager (isCollapsed=true, progress=${viewModel.collapseProgress})")
WeekPager(
selectedDate = viewModel.selectedDate,
today = today,
@ -152,6 +158,7 @@ fun CalendarMonthView(
}
)
} else {
println("$TAG: Showing CalendarPager (isCollapsed=${viewModel.isCollapsed}, progress=${viewModel.collapseProgress})")
CalendarPager(
selectedDate = viewModel.selectedDate,
today = today,
@ -174,6 +181,7 @@ fun CalendarMonthView(
}
if (cardHeightPx > 0) {
println("$TAG: BottomCard height=${with(density) { cardHeightPx.toDp() }}")
BottomCard(
viewModel = viewModel,
modifier = Modifier