Merge pull request #2 from xunrua/main

优化月→年视图切换卡顿:Pager 缓存降为 0 + 移除延迟预组合
This commit is contained in:
Sonetto 2026-05-18 23:04:31 +08:00 committed by GitHub
commit b364c259ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 7 additions and 19 deletions

View File

@ -51,7 +51,6 @@ import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.datetime.DatePeriod import kotlinx.datetime.DatePeriod
import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDate
@ -93,24 +92,11 @@ fun CalendarMonthView(
var screenHeightPx by remember { mutableIntStateOf(0) } var screenHeightPx by remember { mutableIntStateOf(0) }
var calendarContentHeightPx by remember { mutableIntStateOf(0) } var calendarContentHeightPx by remember { mutableIntStateOf(0) }
var isMenuExpanded by remember { mutableStateOf(false) } var isMenuExpanded by remember { mutableStateOf(false) }
var yearPagerBeyondViewport by remember { mutableStateOf(0) }
// 视图切换时自动关闭菜单 // 视图切换时自动关闭菜单
LaunchedEffect(viewModel.isYearView) { LaunchedEffect(viewModel.isYearView) {
isMenuExpanded = false isMenuExpanded = false
} }
// 年视图动画完成后再恢复预组合,避免动画期间触发邻页组合阻塞帧
LaunchedEffect(viewModel.isYearView) {
if (viewModel.isYearView) {
snapshotFlow { viewModel.yearViewProgress }
.first { it >= 1f }
yearPagerBeyondViewport = 1
} else {
yearPagerBeyondViewport = 0
}
}
val pagerState = rememberPagerState(initialPage = START_PAGE, pageCount = { Int.MAX_VALUE }) val pagerState = rememberPagerState(initialPage = START_PAGE, pageCount = { Int.MAX_VALUE })
// 年视图分页器 // 年视图分页器
@ -233,6 +219,9 @@ fun CalendarMonthView(
} }
val monthProgress = 1f - viewModel.yearViewProgress val monthProgress = 1f - viewModel.yearViewProgress
// 组合阶段计算lambda 捕获快照值,避免 draw 阶段读到已更新的 rowHeightPx
// 但 layout 仍用旧值导致行堆叠
val layoutReady = rowHeightPx > 0
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -240,7 +229,7 @@ fun CalendarMonthView(
val scale = lerp(0.3f, 1f, monthProgress) val scale = lerp(0.3f, 1f, monthProgress)
scaleX = scale scaleX = scale
scaleY = scale scaleY = scale
alpha = monthProgress.coerceIn(0f, 1f) alpha = if (layoutReady) monthProgress.coerceIn(0f, 1f) else 0f
transformOrigin = TransformOrigin(anchorPivotX, anchorPivotY) transformOrigin = TransformOrigin(anchorPivotX, anchorPivotY)
} }
) { ) {
@ -361,7 +350,7 @@ fun CalendarMonthView(
) )
HorizontalPager( HorizontalPager(
state = yearPagerState, state = yearPagerState,
beyondViewportPageCount = yearPagerBeyondViewport, beyondViewportPageCount = 0,
flingBehavior = PagerDefaults.flingBehavior(state = yearPagerState), flingBehavior = PagerDefaults.flingBehavior(state = yearPagerState),
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()

View File

@ -67,7 +67,7 @@ fun CalendarPager(
HorizontalPager( HorizontalPager(
state = pagerState, state = pagerState,
beyondViewportPageCount = 1, beyondViewportPageCount = 0,
flingBehavior = PagerDefaults.flingBehavior(state = pagerState), flingBehavior = PagerDefaults.flingBehavior(state = pagerState),
modifier = modifier modifier = modifier
) { page -> ) { page ->

View File

@ -66,7 +66,7 @@ fun WeekPager(
HorizontalPager( HorizontalPager(
state = pagerState, state = pagerState,
beyondViewportPageCount = 1, beyondViewportPageCount = 0,
flingBehavior = PagerDefaults.flingBehavior(state = pagerState), flingBehavior = PagerDefaults.flingBehavior(state = pagerState),
modifier = modifier modifier = modifier
) { page -> ) { page ->

View File

@ -18,7 +18,6 @@ class CalendarViewModelTest {
private val fixedInstant = Instant.parse("2026-05-15T00:00:00Z") private val fixedInstant = Instant.parse("2026-05-15T00:00:00Z")
private val testClock = FixedClock(fixedInstant) private val testClock = FixedClock(fixedInstant)
private fun createViewModel(): CalendarViewModel { private fun createViewModel(): CalendarViewModel {
val scope = CoroutineScope(Dispatchers.Unconfined) val scope = CoroutineScope(Dispatchers.Unconfined)
return CalendarViewModel(coroutineScope = scope, clock = testClock) return CalendarViewModel(coroutineScope = scope, clock = testClock)