行偏移从 offset(Dp) 改为 graphicsLayer(translationY) 避免每帧 layout pass

offset 触发 layout-phase 重测量,trace 中 measure 最高 1266ms。
graphicsLayer 只触发 draw-phase redraw,跳过 layout。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
xfy 2026-05-18 14:53:11 +08:00
parent 72b591ab49
commit 5d6b2071e2

View File

@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -103,16 +102,15 @@ fun CalendarMonthPage(
val isAbove = hasAnchor && weekIndex < anchorIndex val isAbove = hasAnchor && weekIndex < anchorIndex
val isBelow = hasAnchor && weekIndex > anchorIndex val isBelow = hasAnchor && weekIndex > anchorIndex
val yOffsetDp = if (rowHeightPx > 0) { val yOffsetPx = if (rowHeightPx > 0) {
val yPx = when { when {
!hasAnchor -> weekIndex * h - collapseProgress * weeks.size * h !hasAnchor -> weekIndex * h - collapseProgress * weeks.size * h
isAnchor -> anchorIndex * h * (1f - phase1) isAnchor -> anchorIndex * h * (1f - phase1)
isAbove -> weekIndex * h - phase1 * anchorIndex * h isAbove -> weekIndex * h - phase1 * anchorIndex * h
isBelow -> weekIndex * h - phase1 * anchorIndex * h - phase2 * belowRowsHeight isBelow -> weekIndex * h - phase1 * anchorIndex * h - phase2 * belowRowsHeight
else -> weekIndex * h else -> weekIndex * h
} }
with(density) { yPx.toDp() } } else 0f
} else 0.dp
val rowAlpha = when { val rowAlpha = when {
!hasAnchor -> (1f - collapseProgress).coerceIn(0f, 1f) !hasAnchor -> (1f - collapseProgress).coerceIn(0f, 1f)
@ -135,7 +133,10 @@ fun CalendarMonthPage(
if (isAnchor && phase1 >= 1f) Modifier.background(MaterialTheme.colorScheme.surface) if (isAnchor && phase1 >= 1f) Modifier.background(MaterialTheme.colorScheme.surface)
else Modifier else Modifier
) )
.offset(y = yOffsetDp) .graphicsLayer {
translationY = yOffsetPx
alpha = rowAlpha
}
.then( .then(
if (weekIndex == 0 && rowHeightPx == 0) { if (weekIndex == 0 && rowHeightPx == 0) {
Modifier.onSizeChanged { size -> Modifier.onSizeChanged { size ->
@ -146,10 +147,6 @@ fun CalendarMonthPage(
} else Modifier } else Modifier
) )
.padding(vertical = ROW_PADDING_DP.dp) .padding(vertical = ROW_PADDING_DP.dp)
.then(
if (rowAlpha < 1f) Modifier.graphicsLayer { alpha = rowAlpha }
else Modifier
)
) { ) {
week.forEach { dayData -> week.forEach { dayData ->
DayCell( DayCell(