feat: 移除共享元素转场,月/年视图切换改用缩放+淡入淡出动画
This commit is contained in:
parent
1930bbcb7f
commit
4a8480be64
@ -4,7 +4,6 @@ import androidx.compose.animation.AnimatedContent
|
|||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.EnterTransition
|
import androidx.compose.animation.EnterTransition
|
||||||
import androidx.compose.animation.ExitTransition
|
import androidx.compose.animation.ExitTransition
|
||||||
import androidx.compose.animation.SharedTransitionLayout
|
|
||||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||||
import androidx.compose.animation.core.Spring
|
import androidx.compose.animation.core.Spring
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
@ -12,11 +11,8 @@ import androidx.compose.animation.core.spring
|
|||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
|
||||||
import androidx.compose.animation.scaleIn
|
import androidx.compose.animation.scaleIn
|
||||||
import androidx.compose.animation.scaleOut
|
import androidx.compose.animation.scaleOut
|
||||||
import androidx.compose.animation.slideInVertically
|
|
||||||
import androidx.compose.animation.slideOutVertically
|
|
||||||
import androidx.compose.animation.togetherWith
|
import androidx.compose.animation.togetherWith
|
||||||
import androidx.compose.ui.graphics.TransformOrigin
|
import androidx.compose.ui.graphics.TransformOrigin
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
@ -88,14 +84,13 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
|||||||
import plus.rua.project.util.logd
|
import plus.rua.project.util.logd
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日历主界面,包含月/周视图切换、折叠动画和年视图共享元素转场。
|
* 日历主界面,包含月/周视图切换、折叠动画和年视图转场。
|
||||||
*
|
*
|
||||||
* 折叠时日历从月视图收缩为周视图(1行),BottomCard 同步上移填充空间。
|
* 折叠时日历从月视图收缩为周视图(1行),BottomCard 同步上移填充空间。
|
||||||
* 通过左下角 FAB 菜单切换月/年视图,使用 SharedTransitionLayout 实现共享元素转场。
|
* 通过左下角 FAB 菜单切换月/年视图。
|
||||||
*
|
*
|
||||||
* @param modifier 外部布局修饰符
|
* @param modifier 外部布局修饰符
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CalendarMonthView(
|
fun CalendarMonthView(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
@ -185,8 +180,6 @@ fun CalendarMonthView(
|
|||||||
screenWidthPx = size.width
|
screenWidthPx = size.width
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
SharedTransitionLayout {
|
|
||||||
val sharedScope = this
|
|
||||||
var lastLoggedTargetState by remember { mutableStateOf(false) }
|
var lastLoggedTargetState by remember { mutableStateOf(false) }
|
||||||
SideEffect {
|
SideEffect {
|
||||||
if (lastLoggedTargetState != isYearView) {
|
if (lastLoggedTargetState != isYearView) {
|
||||||
@ -198,10 +191,14 @@ fun CalendarMonthView(
|
|||||||
targetState = isYearView,
|
targetState = isYearView,
|
||||||
label = "month_year_transition",
|
label = "month_year_transition",
|
||||||
transitionSpec = {
|
transitionSpec = {
|
||||||
val enter = fadeIn(tween(300, easing = FastOutSlowInEasing)) +
|
val enter = scaleIn(
|
||||||
slideInVertically(tween(300, easing = FastOutSlowInEasing)) { it / 6 }
|
initialScale = 0.85f,
|
||||||
val exit = fadeOut(tween(200, easing = FastOutSlowInEasing)) +
|
animationSpec = tween(350, easing = FastOutSlowInEasing)
|
||||||
slideOutVertically(tween(200, easing = FastOutSlowInEasing)) { -it / 6 }
|
) + fadeIn(tween(250, easing = FastOutSlowInEasing))
|
||||||
|
val exit = scaleOut(
|
||||||
|
targetScale = 0.85f,
|
||||||
|
animationSpec = tween(250, easing = FastOutSlowInEasing)
|
||||||
|
) + fadeOut(tween(200, easing = FastOutSlowInEasing))
|
||||||
enter togetherWith exit
|
enter togetherWith exit
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
@ -261,32 +258,20 @@ fun CalendarMonthView(
|
|||||||
val onRowHeightMeasured = remember {
|
val onRowHeightMeasured = remember {
|
||||||
{ h: Int -> if (h > 0) rowHeightPx = h }
|
{ h: Int -> if (h > 0) rowHeightPx = h }
|
||||||
}
|
}
|
||||||
with(sharedScope) {
|
CalendarPagerArea(
|
||||||
// P0: 缓存 sharedElement tween,避免每次重组创建新实例导致动画重新计算
|
selectedDate = selectedDate,
|
||||||
val sharedTween = remember { tween<androidx.compose.ui.geometry.Rect>(400, easing = FastOutSlowInEasing) }
|
today = today,
|
||||||
CalendarPagerArea(
|
collapseProgress = animatedCollapseProgress,
|
||||||
selectedDate = selectedDate,
|
showLegalHoliday = showLegalHoliday,
|
||||||
today = today,
|
rowHeightPx = rowHeightPx,
|
||||||
collapseProgress = animatedCollapseProgress,
|
screenWidthPx = screenWidthPx,
|
||||||
showLegalHoliday = showLegalHoliday,
|
onDateClick = onDateClick,
|
||||||
rowHeightPx = rowHeightPx,
|
onMonthChanged = onMonthChanged,
|
||||||
screenWidthPx = screenWidthPx,
|
shiftKindAt = shiftKindAt,
|
||||||
onDateClick = onDateClick,
|
onRowHeightMeasured = onRowHeightMeasured,
|
||||||
onMonthChanged = onMonthChanged,
|
pagerState = pagerState,
|
||||||
shiftKindAt = shiftKindAt,
|
modifier = Modifier.clipToBounds()
|
||||||
onRowHeightMeasured = onRowHeightMeasured,
|
)
|
||||||
pagerState = pagerState,
|
|
||||||
modifier = Modifier
|
|
||||||
.sharedElement(
|
|
||||||
sharedContentState = rememberSharedContentState(
|
|
||||||
key = "month_grid_${currentYear}_${currentMonth}"
|
|
||||||
),
|
|
||||||
animatedVisibilityScope = this@AnimatedContent,
|
|
||||||
boundsTransform = { _, _ -> sharedTween }
|
|
||||||
)
|
|
||||||
.clipToBounds()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
BottomCardArea(
|
BottomCardArea(
|
||||||
viewModel = viewModel,
|
viewModel = viewModel,
|
||||||
today = today,
|
today = today,
|
||||||
@ -365,8 +350,6 @@ fun CalendarMonthView(
|
|||||||
coroutineScope.launch { pagerState.scrollToPage(targetPage) }
|
coroutineScope.launch { pagerState.scrollToPage(targetPage) }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sharedTransitionScope = sharedScope,
|
|
||||||
animatedVisibilityScope = this@AnimatedContent,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -374,7 +357,6 @@ fun CalendarMonthView(
|
|||||||
composeTraceEndSection()
|
composeTraceEndSection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// FAB 浮动按钮
|
// FAB 浮动按钮
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
package plus.rua.project.ui
|
package plus.rua.project.ui
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.AnimatedVisibilityScope
|
|
||||||
import androidx.compose.animation.ExperimentalSharedTransitionApi
|
|
||||||
import androidx.compose.animation.SharedTransitionScope
|
|
||||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
@ -74,19 +71,14 @@ private data class MiniMonthColors(
|
|||||||
* @param selectedMonth 当前选中月份(1-12)
|
* @param selectedMonth 当前选中月份(1-12)
|
||||||
* @param today 今天的日期
|
* @param today 今天的日期
|
||||||
* @param onMonthClick 月份点击回调
|
* @param onMonthClick 月份点击回调
|
||||||
* @param sharedTransitionScope 共享元素转场作用域
|
|
||||||
* @param animatedVisibilityScope 动画可见性作用域
|
|
||||||
* @param modifier 外部布局修饰符
|
* @param modifier 外部布局修饰符
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalSharedTransitionApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun YearGridView(
|
fun YearGridView(
|
||||||
year: Int,
|
year: Int,
|
||||||
selectedMonth: Int,
|
selectedMonth: Int,
|
||||||
today: LocalDate,
|
today: LocalDate,
|
||||||
onMonthClick: (Int) -> Unit,
|
onMonthClick: (Int) -> Unit,
|
||||||
sharedTransitionScope: SharedTransitionScope,
|
|
||||||
animatedVisibilityScope: AnimatedVisibilityScope,
|
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val enterT = System.nanoTime()
|
val enterT = System.nanoTime()
|
||||||
@ -176,32 +168,19 @@ fun YearGridView(
|
|||||||
) {
|
) {
|
||||||
(0 until 3).forEach { col ->
|
(0 until 3).forEach { col ->
|
||||||
val month = row * 3 + col + 1
|
val month = row * 3 + col + 1
|
||||||
with(sharedTransitionScope) {
|
MiniMonth(
|
||||||
// P0: 缓存 sharedElement tween,避免每次重组创建新实例
|
year = year,
|
||||||
val miniMonthTween = remember { tween<androidx.compose.ui.geometry.Rect>(400, easing = FastOutSlowInEasing) }
|
month = month,
|
||||||
val seKey = "month_grid_${year}_$month"
|
isSelected = month == selectedMonth,
|
||||||
MiniMonth(
|
today = today,
|
||||||
year = year,
|
days = monthDays[month - 1],
|
||||||
month = month,
|
colors = colors,
|
||||||
isSelected = month == selectedMonth,
|
dayLayouts = dayLayouts,
|
||||||
today = today,
|
titleLayouts = titleLayouts,
|
||||||
days = monthDays[month - 1],
|
weekdayLayouts = weekdayLayouts,
|
||||||
colors = colors,
|
onClick = { onMonthClick(month) },
|
||||||
dayLayouts = dayLayouts,
|
modifier = Modifier.weight(1f)
|
||||||
titleLayouts = titleLayouts,
|
)
|
||||||
weekdayLayouts = weekdayLayouts,
|
|
||||||
onClick = { onMonthClick(month) },
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.sharedElement(
|
|
||||||
sharedContentState = rememberSharedContentState(
|
|
||||||
key = seKey
|
|
||||||
),
|
|
||||||
animatedVisibilityScope = animatedVisibilityScope,
|
|
||||||
boundsTransform = { _, _ -> miniMonthTween }
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user