perf: 引入 logd 条件日志工具,增强动画调试并优化 sharedElement 缓存
- 新增 AnimLog.kt,提供 BuildConfig.DEBUG 条件控制的 logd 日志工具, 支持 lambda 延迟求值以避免 release 模式下的字符串拼接开销 - 全模块替换 android.util.Log.d 为 logd,并将日志重构为 lambda 形式 - CalendarViewModel: toggleYearView / selectMonthFromYearView 添加纳秒级 耗时追踪日志 - CalendarMonthView / CalendarMonthPage / CalendarPager / YearGridView: 增加重组/进入/离开/页面切换/动画状态变化的详细调试日志 - 折叠动画/滑动进度日志添加状态去重,避免频繁重复输出 - P0: 缓存 sharedElement tween 实例(CalendarMonthView + YearGridView), 避免每次重组创建新实例导致动画重新计算 - P0: YearPager pageYear 使用 remember 稳定计算,避免 settledPage 与 yearViewYear 不同步导致抖动 - 移除 YearPager crossFadeAlpha,改为无透明度渐变 - app/build.gradle.kts 添加 profileinstaller 依赖 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
20425e392c
commit
9a0222b4a2
@ -93,6 +93,7 @@ dependencies {
|
||||
|
||||
implementation(platform(libs.compose.bom))
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(libs.androidx.profileinstaller)
|
||||
debugImplementation(libs.compose.uiToolingPreview)
|
||||
debugImplementation(libs.compose.uiTooling)
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ 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 plus.rua.project.util.logd
|
||||
import kotlin.time.Clock
|
||||
|
||||
private const val TAG_VM = "CalendarExpand"
|
||||
@ -210,17 +210,27 @@ class CalendarViewModel(
|
||||
* 当前视图被直接移除;动画只作用在目标视图的 scale/alpha 上。
|
||||
*/
|
||||
fun toggleYearView() {
|
||||
val t0 = System.nanoTime()
|
||||
if (_isYearView.value) {
|
||||
logd(TAG_VM, "[toggleYearView] ===== START Year→Month t=$t0 =====")
|
||||
composeTraceBeginSection("YearView→MonthView")
|
||||
_yearViewProgress.value = 0f
|
||||
logd(TAG_VM, "[toggleYearView] yearViewProgress=0 dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_isYearView.value = false
|
||||
logd(TAG_VM, "[toggleYearView] isYearView=false dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
composeTraceEndSection()
|
||||
logd(TAG_VM, "[toggleYearView] ===== END Year→Month total=${(System.nanoTime() - t0) / 1_000_000}ms =====")
|
||||
} else {
|
||||
logd(TAG_VM, "[toggleYearView] ===== START Month→Year t=$t0 =====")
|
||||
composeTraceBeginSection("MonthView→YearView")
|
||||
_yearViewYear.value = _selectedDate.value.year
|
||||
logd(TAG_VM, "[toggleYearView] yearViewYear=${_yearViewYear.value} dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_yearViewProgress.value = 1f
|
||||
logd(TAG_VM, "[toggleYearView] yearViewProgress=1 dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_isYearView.value = true
|
||||
logd(TAG_VM, "[toggleYearView] isYearView=true dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
composeTraceEndSection()
|
||||
logd(TAG_VM, "[toggleYearView] ===== END Month→Year total=${(System.nanoTime() - t0) / 1_000_000}ms =====")
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,13 +246,20 @@ class CalendarViewModel(
|
||||
*/
|
||||
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
||||
fun selectMonthFromYearView(month: Int) {
|
||||
val t0 = System.nanoTime()
|
||||
logd(TAG_VM, "[selectMonthFromYearView] ===== START month=$month t=$t0 =====")
|
||||
composeTraceBeginSection("YearView:SelectMonth")
|
||||
val date = if (_yearViewYear.value == today.year && today.month.number == month) today
|
||||
else LocalDate(_yearViewYear.value, month, 1)
|
||||
logd(TAG_VM, "[selectMonthFromYearView] targetDate=$date dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_selectedDate.value = date
|
||||
logd(TAG_VM, "[selectMonthFromYearView] selectedDate set dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_isYearView.value = false
|
||||
logd(TAG_VM, "[selectMonthFromYearView] isYearView=false dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_yearViewProgress.value = 0f
|
||||
logd(TAG_VM, "[selectMonthFromYearView] yearViewProgress=0 dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
composeTraceEndSection()
|
||||
logd(TAG_VM, "[selectMonthFromYearView] ===== END total=${(System.nanoTime() - t0) / 1_000_000}ms =====")
|
||||
}
|
||||
|
||||
fun incrementYear() {
|
||||
@ -290,7 +307,7 @@ class CalendarViewModel(
|
||||
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}")
|
||||
logd(TAG_VM, "onExpandDrag: delta=$delta old=$old new=${_collapseProgress.value}")
|
||||
}
|
||||
|
||||
/**
|
||||
@ -309,7 +326,7 @@ class CalendarViewModel(
|
||||
_collapseProgress.value = 1f
|
||||
"COLLAPSED (bounce back)"
|
||||
}
|
||||
Log.d(TAG_VM, "onExpandDragEnd: progress=$progress threshold=${1 - COLLAPSE_THRESHOLD} result=$result")
|
||||
logd(TAG_VM, "onExpandDragEnd: progress=$progress threshold=${1 - COLLAPSE_THRESHOLD} result=$result")
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -21,7 +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 plus.rua.project.util.logd
|
||||
import kotlinx.datetime.DatePeriod
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlinx.datetime.minus
|
||||
@ -109,13 +109,13 @@ fun CalendarMonthPage(
|
||||
|
||||
// 全局动画参数日志(每次重组)
|
||||
val pageFrameNs = System.nanoTime()
|
||||
Log.d(
|
||||
TAG_CMP,
|
||||
"Page[$year-$month]: anchorIndex=$anchorIndex weeksSize=${weeks.size} " +
|
||||
val totalCells = weeks.size * 7
|
||||
logd(TAG_CMP) {
|
||||
"Page[$year-$month]: anchorIndex=$anchorIndex weeksSize=${weeks.size} totalCells=$totalCells " +
|
||||
"phase1End=${if (anchorIndex > 0 && weeks.size > 1) anchorIndex.toFloat() / (weeks.size - 1) else 0f} " +
|
||||
"effectiveWeeks=$effectiveWeeks rowHeightPx=$rowHeightPx " +
|
||||
"collapseProgress=$collapseProgress frameNs=$pageFrameNs"
|
||||
)
|
||||
"collapseProgress=$collapseProgress lunarMapSize=${lunarDataMap.size} frameNs=$pageFrameNs"
|
||||
}
|
||||
|
||||
val totalHeightDp = if (rowHeightPx > 0) {
|
||||
val h = rowHeightPx.toFloat()
|
||||
@ -213,8 +213,7 @@ private fun WeekRow(
|
||||
}
|
||||
|
||||
val frameTimeNs = System.nanoTime()
|
||||
Log.d(
|
||||
TAG_CMP,
|
||||
logd(TAG_CMP) {
|
||||
"WeekRow[$weekIndex]: " +
|
||||
"isAnchor=$isAnchor isAbove=$isAbove isBelow=$isBelow " +
|
||||
"phase1=$phase1 phase2=$phase2 phase1End=$phase1End " +
|
||||
@ -222,7 +221,7 @@ private fun WeekRow(
|
||||
"yOffsetPx=$yOffsetPx rowAlpha=$rowAlpha " +
|
||||
"collapseProgress=$collapseProgress " +
|
||||
"frameNs=$frameTimeNs"
|
||||
)
|
||||
}
|
||||
|
||||
if (rowAlpha > 0.01f) {
|
||||
Row(
|
||||
|
||||
@ -82,7 +82,7 @@ import plus.rua.project.composeTraceEndSection
|
||||
import kotlin.math.abs
|
||||
import kotlin.time.Clock
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import android.util.Log
|
||||
import plus.rua.project.util.logd
|
||||
|
||||
/**
|
||||
* 日历主界面,包含月/周视图切换、折叠动画和年视图共享元素转场。
|
||||
@ -119,8 +119,13 @@ fun CalendarMonthView(
|
||||
animationSpec = spring(stiffness = Spring.StiffnessMedium),
|
||||
label = "collapseProgress"
|
||||
)
|
||||
var lastLoggedCollapse by remember { mutableStateOf(-1f) }
|
||||
SideEffect {
|
||||
Log.d("CalendarExpandAnim", "View: target=$collapseProgress animated=$animatedCollapseProgress isCollapsed=$isCollapsed")
|
||||
if (kotlin.math.abs(lastLoggedCollapse - collapseProgress) > 0.001f) {
|
||||
lastLoggedCollapse = collapseProgress
|
||||
logd("AnimLog", "[Collapse] target=$collapseProgress animated=$animatedCollapseProgress isCollapsed=$isCollapsed")
|
||||
}
|
||||
logd("AnimLog", "[MonthView] isYearView=$isYearView isCollapsed=$isCollapsed collapseProgress=$collapseProgress animated=$animatedCollapseProgress selectedDate=$selectedDate yearViewYear=$yearViewYear")
|
||||
}
|
||||
|
||||
val density = LocalDensity.current
|
||||
@ -178,6 +183,13 @@ fun CalendarMonthView(
|
||||
) {
|
||||
SharedTransitionLayout {
|
||||
val sharedScope = this
|
||||
var lastLoggedTargetState by remember { mutableStateOf(false) }
|
||||
SideEffect {
|
||||
if (lastLoggedTargetState != isYearView) {
|
||||
lastLoggedTargetState = isYearView
|
||||
logd("AnimLog", "[AnimatedContent] ★ targetState CHANGE isYearView=$isYearView t=${System.nanoTime()}")
|
||||
}
|
||||
}
|
||||
AnimatedContent(
|
||||
targetState = isYearView,
|
||||
label = "month_year_transition",
|
||||
@ -191,6 +203,13 @@ fun CalendarMonthView(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) { yearViewActive ->
|
||||
if (!yearViewActive) {
|
||||
androidx.compose.runtime.DisposableEffect(Unit) {
|
||||
val t = System.nanoTime()
|
||||
logd("AnimLog", "[MonthView] ★★★ ENTER composable t=$t")
|
||||
onDispose {
|
||||
logd("AnimLog", "[MonthView] ★★★ LEAVE composable alive=${(System.nanoTime() - t) / 1_000_000}ms")
|
||||
}
|
||||
}
|
||||
composeTraceBeginSection("MonthView:Compose")
|
||||
composeTraceBeginSection("CalendarPagerArea")
|
||||
val layoutReady = rowHeightPx > 0
|
||||
@ -239,6 +258,8 @@ fun CalendarMonthView(
|
||||
{ h: Int -> if (h > 0) rowHeightPx = h }
|
||||
}
|
||||
with(sharedScope) {
|
||||
// P0: 缓存 sharedElement tween,避免每次重组创建新实例导致动画重新计算
|
||||
val sharedTween = remember { tween<androidx.compose.ui.geometry.Rect>(400, easing = FastOutSlowInEasing) }
|
||||
CalendarPagerArea(
|
||||
selectedDate = selectedDate,
|
||||
today = today,
|
||||
@ -257,9 +278,7 @@ fun CalendarMonthView(
|
||||
key = "month_grid_${currentYear}_${currentMonth}"
|
||||
),
|
||||
animatedVisibilityScope = this@AnimatedContent,
|
||||
boundsTransform = { _, _ ->
|
||||
tween(400, easing = FastOutSlowInEasing)
|
||||
}
|
||||
boundsTransform = { _, _ -> sharedTween }
|
||||
)
|
||||
.clipToBounds()
|
||||
)
|
||||
@ -276,6 +295,13 @@ fun CalendarMonthView(
|
||||
composeTraceEndSection()
|
||||
composeTraceEndSection()
|
||||
} else {
|
||||
androidx.compose.runtime.DisposableEffect(Unit) {
|
||||
val t = System.nanoTime()
|
||||
logd("AnimLog", "[YearView] ★★★ ENTER composable t=$t")
|
||||
onDispose {
|
||||
logd("AnimLog", "[YearView] ★★★ LEAVE composable alive=${(System.nanoTime() - t) / 1_000_000}ms")
|
||||
}
|
||||
}
|
||||
composeTraceBeginSection("YearView:Compose")
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@ -294,6 +320,13 @@ fun CalendarMonthView(
|
||||
}
|
||||
}
|
||||
)
|
||||
var lastLoggedYearPage by remember { mutableIntStateOf(-1) }
|
||||
SideEffect {
|
||||
if (lastLoggedYearPage != yearPagerState.currentPage) {
|
||||
lastLoggedYearPage = yearPagerState.currentPage
|
||||
logd("AnimLog", "[YearPager] page=${yearPagerState.currentPage} settledPage=${yearPagerState.settledPage} offset=${yearPagerState.currentPageOffsetFraction}")
|
||||
}
|
||||
}
|
||||
HorizontalPager(
|
||||
state = yearPagerState,
|
||||
beyondViewportPageCount = 0,
|
||||
@ -302,19 +335,21 @@ fun CalendarMonthView(
|
||||
.fillMaxWidth()
|
||||
.weight(1f)
|
||||
) { page ->
|
||||
val pageOffset = abs(yearPagerState.currentPageOffsetFraction)
|
||||
val isCurrentPage = page == yearPagerState.currentPage
|
||||
val crossFadeAlpha = if (isCurrentPage) {
|
||||
1f - pageOffset
|
||||
} else {
|
||||
pageOffset
|
||||
// P0: 稳定 pageYear 计算,避免 settledPage/yearViewYear 不同步导致抖动
|
||||
val pageYear = remember(page, yearViewYear, yearPagerState.settledPage) {
|
||||
yearViewYear + (page - yearPagerState.settledPage)
|
||||
}
|
||||
val isCurrentPage = page == yearPagerState.currentPage
|
||||
if (isCurrentPage) {
|
||||
logd("AnimLog") { "[YearPager] Compose page=$page year=$pageYear" }
|
||||
}
|
||||
val pageYear = yearViewYear + (page - yearPagerState.settledPage)
|
||||
YearGridView(
|
||||
year = pageYear,
|
||||
selectedMonth = if (pageYear == currentYear) currentMonth else 0,
|
||||
today = today,
|
||||
onMonthClick = { month ->
|
||||
val clickT = System.nanoTime()
|
||||
logd("AnimLog") { "[YearGridView] MonthClick month=$month year=$pageYear t=$clickT" }
|
||||
viewModel.selectMonthFromYearView(month)
|
||||
@Suppress("DEPRECATION") // monthNumber 无替代 API
|
||||
val targetPage = yearMonthToPage(
|
||||
@ -322,12 +357,13 @@ fun CalendarMonthView(
|
||||
today.year, today.month.number
|
||||
)
|
||||
if (targetPage != pagerState.currentPage) {
|
||||
logd("AnimLog") { "[YearPager] scrollToPage target=$targetPage" }
|
||||
coroutineScope.launch { pagerState.scrollToPage(targetPage) }
|
||||
}
|
||||
},
|
||||
sharedTransitionScope = sharedScope,
|
||||
animatedVisibilityScope = this@AnimatedContent,
|
||||
modifier = Modifier.alpha(crossFadeAlpha)
|
||||
modifier = Modifier
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -477,12 +513,13 @@ private fun CalendarPagerArea(
|
||||
pagerState: PagerState,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val t0 = System.nanoTime()
|
||||
val density = LocalDensity.current
|
||||
|
||||
val interpolatedWeeks by remember {
|
||||
derivedStateOf {
|
||||
val fraction = pagerState.currentPageOffsetFraction
|
||||
if (abs(fraction) > OFFSET_FRACTION_THRESHOLD) {
|
||||
val result = if (abs(fraction) > OFFSET_FRACTION_THRESHOLD) {
|
||||
val cp = pagerState.currentPage
|
||||
val baseWeeks = calculateWeeksCountForPage(cp, today)
|
||||
val targetPage = cp + if (fraction > 0) 1 else -1
|
||||
@ -491,6 +528,8 @@ private fun CalendarPagerArea(
|
||||
} else {
|
||||
calculateWeeksCountForPage(pagerState.currentPage, today).toFloat()
|
||||
}
|
||||
logd("AnimLog", "[PagerArea] interpolatedWeeks=$result fraction=$fraction page=${pagerState.currentPage}")
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
@ -514,6 +553,8 @@ private fun CalendarPagerArea(
|
||||
}
|
||||
} else 0
|
||||
|
||||
logd("AnimLog", "[PagerArea] gridHeightPx=$gridHeightPx effectiveRowHeightPx=$effectiveRowHeightPx effectiveWeeks=$effectiveWeeks collapseProgress=$collapseProgress screenW=$screenWidthPx rowH=$rowHeightPx dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
|
||||
val pagerModifier = if (rowHeightPx > 0 && gridHeightPx > 0) {
|
||||
Modifier
|
||||
.height(with(density) { gridHeightPx.toDp() })
|
||||
@ -559,17 +600,27 @@ private fun BottomCardArea(
|
||||
animationSpec = tween(350, delayMillis = 100, easing = FastOutSlowInEasing),
|
||||
label = "bottomCardSlide"
|
||||
)
|
||||
var lastLoggedSlide by remember { mutableStateOf(-1f) }
|
||||
SideEffect {
|
||||
if (kotlin.math.abs(lastLoggedSlide - slideProgress) > 0.001f) {
|
||||
lastLoggedSlide = slideProgress
|
||||
logd("AnimLog", "[BottomCard] slideProgress=$slideProgress isYearView=$isYearView")
|
||||
}
|
||||
}
|
||||
// 延迟一帧显示 BottomCard,避免 AnimatedGif 和 lunar 计算阻塞首帧
|
||||
var hasLoaded by remember { mutableStateOf(false) }
|
||||
LaunchedEffect(Unit) {
|
||||
delay(32)
|
||||
hasLoaded = true
|
||||
logd("AnimLog", "[BottomCard] hasLoaded=true after delay")
|
||||
}
|
||||
val shouldShow = hasLoaded
|
||||
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
val shiftKind = viewModel.shiftKindAt(uiState.selectedDate)
|
||||
|
||||
logd("AnimLog", "[BottomCard] shouldShow=$shouldShow isYearView=$isYearView slideProgress=$slideProgress dragRangePx=$dragRangePx rowHeightPx=$rowHeightPx")
|
||||
|
||||
if (shouldShow) {
|
||||
BottomCard(
|
||||
isCollapsed = uiState.isCollapsed,
|
||||
|
||||
@ -5,12 +5,16 @@ import androidx.compose.foundation.pager.PagerDefaults
|
||||
import androidx.compose.foundation.pager.PagerState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Modifier
|
||||
import plus.rua.project.util.logd
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.launch
|
||||
@ -75,6 +79,14 @@ fun CalendarPager(
|
||||
derivedStateOf { pagerState.currentPage }
|
||||
}
|
||||
|
||||
var lastLoggedPage by remember { mutableIntStateOf(-1) }
|
||||
SideEffect {
|
||||
if (lastLoggedPage != pagerState.currentPage) {
|
||||
lastLoggedPage = pagerState.currentPage
|
||||
logd("AnimLog", "[CalendarPager] page=${pagerState.currentPage} settledPage=${pagerState.settledPage} offsetFraction=${pagerState.currentPageOffsetFraction}")
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalPager(
|
||||
state = pagerState,
|
||||
beyondViewportPageCount = 0,
|
||||
@ -89,12 +101,16 @@ fun CalendarPager(
|
||||
pageOffset
|
||||
}
|
||||
val (year, month) = pageToYearMonth(page, initialYear, initialMonth)
|
||||
if (isCurrentPage) {
|
||||
logd("AnimLog", "[CalendarPager] Compose page=$page ($year-$month) alpha=$alpha pageOffset=$pageOffset")
|
||||
}
|
||||
CalendarMonthPage(
|
||||
year = year,
|
||||
month = month,
|
||||
selectedDate = selectedDate,
|
||||
today = today,
|
||||
onDateClick = { date ->
|
||||
val clickT = System.nanoTime()
|
||||
onDateClick(date)
|
||||
// 点击跨月日期时,滚动到该月对应的页
|
||||
val clickedYear = date.year
|
||||
@ -105,6 +121,7 @@ fun CalendarPager(
|
||||
val targetPage =
|
||||
yearMonthToPage(clickedYear, clickedMonth, initialYear, initialMonth)
|
||||
if (targetPage != pagerState.currentPage) {
|
||||
logd("AnimLog", "[CalendarPager] Cross-month click date=$date targetPage=$targetPage t=$clickT")
|
||||
coroutineScope.launch {
|
||||
pagerState.animateScrollToPage(targetPage)
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import plus.rua.project.util.logd
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
@ -87,6 +88,14 @@ fun YearGridView(
|
||||
animatedVisibilityScope: AnimatedVisibilityScope,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val enterT = System.nanoTime()
|
||||
logd("AnimLog", "[YearGridView] ★★★ ENTER year=$year selectedMonth=$selectedMonth t=$enterT")
|
||||
androidx.compose.runtime.DisposableEffect(year) {
|
||||
logd("AnimLog", "[YearGridView] DisposableEffect attached year=$year")
|
||||
onDispose {
|
||||
logd("AnimLog", "[YearGridView] ★★★ LEAVE year=$year alive=${(System.nanoTime() - enterT) / 1_000_000}ms")
|
||||
}
|
||||
}
|
||||
composeTraceBeginSection("YearGridView:$year")
|
||||
|
||||
// P0-F: 主题色在 YearGridView 级别一次性读取并缓存
|
||||
@ -165,6 +174,9 @@ fun YearGridView(
|
||||
(0 until 3).forEach { col ->
|
||||
val month = row * 3 + col + 1
|
||||
with(sharedTransitionScope) {
|
||||
// P0: 缓存 sharedElement tween,避免每次重组创建新实例
|
||||
val miniMonthTween = remember { tween<androidx.compose.ui.geometry.Rect>(400, easing = FastOutSlowInEasing) }
|
||||
val seKey = "month_grid_${year}_$month"
|
||||
MiniMonth(
|
||||
year = year,
|
||||
month = month,
|
||||
@ -180,12 +192,10 @@ fun YearGridView(
|
||||
.weight(1f)
|
||||
.sharedElement(
|
||||
sharedContentState = rememberSharedContentState(
|
||||
key = "month_grid_${year}_$month"
|
||||
key = seKey
|
||||
),
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
boundsTransform = { _, _ ->
|
||||
tween(400, easing = FastOutSlowInEasing)
|
||||
}
|
||||
boundsTransform = { _, _ -> miniMonthTween }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
18
core/src/main/kotlin/plus/rua/project/util/AnimLog.kt
Normal file
18
core/src/main/kotlin/plus/rua/project/util/AnimLog.kt
Normal file
@ -0,0 +1,18 @@
|
||||
package plus.rua.project.util
|
||||
|
||||
import android.util.Log
|
||||
import plus.rua.project.shared.BuildConfig
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun logd(tag: String, message: () -> String) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(tag, message())
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun logd(tag: String, message: String) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(tag, message)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user