Mình có một time picker dạng bánh xe: item ở giữa to và đậm, item càng xa tâm càng nhỏ và mờ. Bản đầu viết kiểu quen tay nhất: theo dõi centerIndex bằng snapshotFlow trên firstVisibleItemIndex, mỗi item giữ 3 animateXAsState cho fontSize, fontWeight và color.
Trên máy mid-range nó giật thấy rõ. Đếm lại thì mỗi frame cuộn tốn khoảng 25 lần recompose: centerIndex đổi kéo theo cả LazyColumn, 5 item đang hiện nhân 3 animation state là thêm 15 trigger, cộng một buffer offscreen để làm hiệu ứng mờ hai đầu.
Compose chạy 3 phase: Composition, Layout, Draw. animateXAsState tạo state mới mỗi frame nên cả 3 phase chạy lại. Lambda của Modifier.graphicsLayer đọc state lúc vẽ, nên khi chỉ đổi scaleX, alpha, rotationX hay translationY, Compose bỏ qua hai phase đầu và chỉ vẽ lại.
Bản sửa bỏ hết state theo item. Mỗi item tự tính khoảng cách từ tâm của nó tới tâm viewport ngay trong graphicsLayer:
Box(Modifier.graphicsLayer {
val info = listState.layoutInfo
val viewportCenter = info.viewportStartOffset + info.viewportSize.height / 2f
val itemCenter = info.visibleItemsInfo
.firstOrNull { it.index == index + halfVisible }
?.let { it.offset + it.size / 2f } ?: viewportCenter
val distance = (abs(itemCenter - viewportCenter) / itemHeightPx).coerceIn(0f, 2f)
val eased = (distance / 2f).let { it * it }
scaleX = lerp(1f, 0.3f, eased)
scaleY = scaleX
alpha = scaleX
})
Kết quả: 0 recomposition mỗi frame cuộn, không còn Animatable nào.
Hai chỗ sửa đi kèm. Callback chọn giá trị chỉ bắn khi cuộn dừng: snapshotFlow { listState.isScrollInProgress }.distinctUntilChanged(), gọi onSelectedChanged khi giá trị về false. Hiệu ứng mờ hai đầu vẽ bằng hai drawRect gradient đè lên nội dung trong drawWithContent, thay cho CompositingStrategy.Offscreen với BlendMode.DstIn, nên không còn cấp buffer offscreen.
Kiểm nhanh bằng Layout Inspector: xem cột recomposition count trong lúc cuộn. Số đó còn nhảy theo frame là vẫn còn state bị đọc ở composition.
Bài đầy đủ kèm rotationX, translationY và bảng so sánh trước sau: https://dantech.academy/blog/android/graphicslayer-chong-recomposition-jetpack-compose
liked this





