feat: 使用 AnimatedContent 平滑切换 CalendarPager ↔ WeekPager
- 用 AnimatedContent 包装 pager 切换,添加 fadeIn/fadeOut 过渡 - 延迟 50ms 切换避免折叠 spring 动画期间的视觉跳跃 - 修复 WeekRow 下方行的 yOffset 计算(移除 phase2 项) - WeekPager 添加农历缓存支持 - 添加折叠动画调试日志 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4c53f234cf
commit
2592a5fa55
@ -20,8 +20,11 @@ import kotlinx.datetime.plus
|
||||
import kotlinx.datetime.todayIn
|
||||
import plus.rua.project.ui.COLLAPSE_THRESHOLD
|
||||
import plus.rua.project.ui.getMonthGridInfo
|
||||
import android.util.Log
|
||||
import kotlin.time.Clock
|
||||
|
||||
private const val TAG_VM = "CalendarExpand"
|
||||
|
||||
/**
|
||||
* 日历日期数据,用于网格单元格渲染。
|
||||
*
|
||||
@ -285,7 +288,9 @@ class CalendarViewModel(
|
||||
* @param delta 拖拽增量,已归一化到 [0,1] 区间
|
||||
*/
|
||||
fun onExpandDrag(delta: Float) {
|
||||
val old = _collapseProgress.value
|
||||
_collapseProgress.value = (_collapseProgress.value + delta).coerceIn(0f, 1f)
|
||||
Log.d(TAG_VM, "onExpandDrag: delta=$delta old=$old new=${_collapseProgress.value}")
|
||||
}
|
||||
|
||||
/**
|
||||
@ -295,13 +300,16 @@ class CalendarViewModel(
|
||||
*/
|
||||
fun onExpandDragEnd() {
|
||||
val progress = _collapseProgress.value
|
||||
if (progress < (1 - COLLAPSE_THRESHOLD)) {
|
||||
val result = if (progress < (1 - COLLAPSE_THRESHOLD)) {
|
||||
_isCollapsed.value = false
|
||||
_collapseProgress.value = 0f
|
||||
"EXPANDED"
|
||||
} else {
|
||||
_isCollapsed.value = true
|
||||
_collapseProgress.value = 1f
|
||||
"COLLAPSED (bounce back)"
|
||||
}
|
||||
Log.d(TAG_VM, "onExpandDragEnd: progress=$progress threshold=${1 - COLLAPSE_THRESHOLD} result=$result")
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -21,6 +21,7 @@ import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import android.util.Log
|
||||
import kotlinx.datetime.DatePeriod
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlinx.datetime.minus
|
||||
@ -30,6 +31,8 @@ import plus.rua.project.DayCellInfo
|
||||
import plus.rua.project.LunarCache
|
||||
import plus.rua.project.ShiftKind
|
||||
|
||||
private const val TAG_CMP = "CalendarExpandAnim"
|
||||
|
||||
|
||||
/**
|
||||
* 月度日历网格页面,支持两阶段折叠动画。
|
||||
@ -185,7 +188,7 @@ private fun WeekRow(
|
||||
!hasAnchor -> weekIndex * h - collapseProgress * weeksSize * h
|
||||
isAnchor -> anchorIndex * h * (1f - phase1)
|
||||
isAbove -> weekIndex * h - phase1 * anchorIndex * h
|
||||
isBelow -> weekIndex * h - phase1 * anchorIndex * h - phase2 * belowRowsHeight
|
||||
isBelow -> weekIndex * h - phase1 * anchorIndex * h
|
||||
else -> weekIndex * h
|
||||
}
|
||||
} else 0f
|
||||
@ -198,6 +201,10 @@ private fun WeekRow(
|
||||
else -> 1f
|
||||
}
|
||||
|
||||
if (isAnchor || isBelow) {
|
||||
Log.d(TAG_CMP, "WeekRow[$weekIndex]: isAnchor=$isAnchor isAbove=$isAbove isBelow=$isBelow phase1=$phase1 phase2=$phase2 yOffsetPx=$yOffsetPx rowAlpha=$rowAlpha collapseProgress=$collapseProgress")
|
||||
}
|
||||
|
||||
if (rowAlpha > 0.01f) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
|
||||
@ -520,20 +520,66 @@ private fun CalendarPagerArea(
|
||||
modifier
|
||||
}
|
||||
|
||||
CalendarPager(
|
||||
selectedDate = selectedDate,
|
||||
today = today,
|
||||
onDateClick = onDateClick,
|
||||
onMonthChanged = onMonthChanged,
|
||||
collapseProgress = collapseProgress,
|
||||
rowHeightPx = rowHeightPx,
|
||||
effectiveWeeks = effectiveWeeks,
|
||||
shiftKindAt = shiftKindAt,
|
||||
showLegalHoliday = showLegalHoliday,
|
||||
onRowHeightMeasured = onRowHeightMeasured,
|
||||
pagerState = pagerState,
|
||||
// 延迟切换:等折叠 spring 动画完全稳定后再切到 WeekPager,避免视觉跳跃
|
||||
var showWeekPager by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(isCollapsed, collapseProgress) {
|
||||
if (isCollapsed && collapseProgress >= 0.999f) {
|
||||
delay(50)
|
||||
showWeekPager = true
|
||||
} else if (!isCollapsed) {
|
||||
showWeekPager = false
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedContent(
|
||||
targetState = showWeekPager,
|
||||
transitionSpec = { fadeIn(tween(80)) togetherWith fadeOut(tween(80)) },
|
||||
label = "pager_switch",
|
||||
modifier = pagerModifier
|
||||
)
|
||||
) { useWeekPager ->
|
||||
if (useWeekPager) {
|
||||
WeekPager(
|
||||
selectedDate = selectedDate,
|
||||
today = today,
|
||||
onDateClick = onDateClick,
|
||||
onWeekChanged = { weekMonday ->
|
||||
val weekSunday = weekMonday.plus(DatePeriod(days = 6))
|
||||
val date = when {
|
||||
today in weekMonday..weekSunday -> today
|
||||
weekMonday.month != weekSunday.month -> {
|
||||
if (weekMonday < selectedDate) {
|
||||
@Suppress("DEPRECATION")
|
||||
LocalDate(weekSunday.year, weekSunday.month.number, 1)
|
||||
} else {
|
||||
weekMonday
|
||||
}
|
||||
}
|
||||
else -> weekMonday
|
||||
}
|
||||
onDateClick(date)
|
||||
},
|
||||
shiftKindAt = shiftKindAt,
|
||||
showLegalHoliday = showLegalHoliday,
|
||||
modifier = Modifier
|
||||
)
|
||||
} else {
|
||||
CalendarPager(
|
||||
selectedDate = selectedDate,
|
||||
today = today,
|
||||
onDateClick = onDateClick,
|
||||
onMonthChanged = onMonthChanged,
|
||||
collapseProgress = collapseProgress,
|
||||
rowHeightPx = rowHeightPx,
|
||||
effectiveWeeks = effectiveWeeks,
|
||||
shiftKindAt = shiftKindAt,
|
||||
showLegalHoliday = showLegalHoliday,
|
||||
onRowHeightMeasured = onRowHeightMeasured,
|
||||
pagerState = pagerState,
|
||||
modifier = Modifier
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@ -18,10 +18,13 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.datetime.DatePeriod
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlinx.datetime.daysUntil
|
||||
import kotlinx.datetime.plus
|
||||
import plus.rua.project.DayCellInfo
|
||||
import plus.rua.project.LunarCache
|
||||
import plus.rua.project.ShiftKind
|
||||
import plus.rua.project.composeTraceBeginSection
|
||||
import plus.rua.project.composeTraceEndSection
|
||||
@ -96,6 +99,11 @@ fun WeekPager(
|
||||
) {
|
||||
(0 until 7).forEach { dayOffset ->
|
||||
val date = weekMonday.plus(DatePeriod(days = dayOffset))
|
||||
val lunarData = remember(date) {
|
||||
runBlocking {
|
||||
LunarCache.default.getOrCompute(date)
|
||||
}
|
||||
}
|
||||
DayCell(
|
||||
date = date,
|
||||
isCurrentMonth = date.month == selectedDate.month
|
||||
@ -106,7 +114,8 @@ fun WeekPager(
|
||||
showLegalHoliday = showLegalHoliday,
|
||||
onClick = { onDateClick(date) },
|
||||
modifier = Modifier.weight(1f),
|
||||
interactionSource = interactionSource
|
||||
interactionSource = interactionSource,
|
||||
lunarData = lunarData
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user