feat(ui): 基于 SharedTransitionLayout 重构年月视图穿梭缩放动画
This commit is contained in:
parent
de1e3178f6
commit
53086f38e0
@ -6,10 +6,13 @@ 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.ExperimentalSharedTransitionApi
|
||||||
|
import androidx.compose.animation.SharedTransitionLayout
|
||||||
|
import androidx.compose.animation.SharedTransitionScope
|
||||||
|
import androidx.compose.animation.core.Animatable
|
||||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||||
import androidx.compose.animation.core.LinearOutSlowInEasing
|
import androidx.compose.animation.core.LinearOutSlowInEasing
|
||||||
import androidx.compose.animation.core.Spring
|
import androidx.compose.animation.core.Spring
|
||||||
import androidx.compose.animation.core.Animatable
|
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.core.spring
|
import androidx.compose.animation.core.spring
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
@ -213,18 +216,22 @@ fun CalendarMonthView(
|
|||||||
screenWidthPx = size.width
|
screenWidthPx = size.width
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
SharedTransitionLayout(
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
) {
|
||||||
AnimatedContent(
|
AnimatedContent(
|
||||||
targetState = isYearView,
|
targetState = isYearView,
|
||||||
label = "month_year_transition",
|
label = "month_year_transition",
|
||||||
transitionSpec = {
|
transitionSpec = {
|
||||||
|
val spatialEasing = FastOutSlowInEasing
|
||||||
val enter = scaleIn(
|
val enter = scaleIn(
|
||||||
initialScale = 0.85f,
|
initialScale = 0.92f,
|
||||||
animationSpec = tween(350, easing = FastOutSlowInEasing)
|
animationSpec = tween(380, easing = spatialEasing)
|
||||||
) + fadeIn(tween(350, easing = LinearOutSlowInEasing))
|
) + fadeIn(tween(380, easing = spatialEasing))
|
||||||
val exit = scaleOut(
|
val exit = scaleOut(
|
||||||
targetScale = 0.85f,
|
targetScale = 0.92f,
|
||||||
animationSpec = tween(350, easing = FastOutSlowInEasing)
|
animationSpec = tween(380, easing = spatialEasing)
|
||||||
) + fadeOut(tween(350, easing = FastOutSlowInEasing))
|
) + fadeOut(tween(380, easing = spatialEasing))
|
||||||
enter togetherWith exit
|
enter togetherWith exit
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
@ -289,7 +296,15 @@ fun CalendarMonthView(
|
|||||||
shiftKindAt = shiftKindAt,
|
shiftKindAt = shiftKindAt,
|
||||||
onRowHeightMeasured = onRowHeightMeasured,
|
onRowHeightMeasured = onRowHeightMeasured,
|
||||||
pagerState = pagerState,
|
pagerState = pagerState,
|
||||||
modifier = Modifier.clipToBounds()
|
modifier = Modifier
|
||||||
|
.clipToBounds()
|
||||||
|
.sharedBounds(
|
||||||
|
sharedContentState = rememberSharedContentState(key = "month_grid_$currentMonth"),
|
||||||
|
animatedVisibilityScope = this@AnimatedContent,
|
||||||
|
boundsTransform = { _, _ ->
|
||||||
|
spring(stiffness = Spring.StiffnessMediumLow, dampingRatio = Spring.DampingRatioNoBouncy)
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
BottomCardArea(
|
BottomCardArea(
|
||||||
viewModel = viewModel,
|
viewModel = viewModel,
|
||||||
@ -349,6 +364,15 @@ fun CalendarMonthView(
|
|||||||
}
|
}
|
||||||
composeTraceEndSection()
|
composeTraceEndSection()
|
||||||
},
|
},
|
||||||
|
monthModifier = { month ->
|
||||||
|
Modifier.sharedBounds(
|
||||||
|
sharedContentState = rememberSharedContentState(key = "month_grid_$month"),
|
||||||
|
animatedVisibilityScope = this@AnimatedContent,
|
||||||
|
boundsTransform = { _, _ ->
|
||||||
|
spring(stiffness = Spring.StiffnessMediumLow, dampingRatio = Spring.DampingRatioNoBouncy)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -356,7 +380,7 @@ fun CalendarMonthView(
|
|||||||
composeTraceEndSection()
|
composeTraceEndSection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// FAB 浮动按钮
|
// FAB 浮动按钮
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
onClick = { isMenuExpanded = !isMenuExpanded },
|
onClick = { isMenuExpanded = !isMenuExpanded },
|
||||||
|
|||||||
@ -77,7 +77,8 @@ fun YearGridView(
|
|||||||
selectedMonth: Int,
|
selectedMonth: Int,
|
||||||
today: LocalDate,
|
today: LocalDate,
|
||||||
onMonthClick: (Int) -> Unit,
|
onMonthClick: (Int) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier,
|
||||||
|
monthModifier: @Composable (Int) -> Modifier = { Modifier }
|
||||||
) {
|
) {
|
||||||
composeTraceBeginSection("YearGridView:$year")
|
composeTraceBeginSection("YearGridView:$year")
|
||||||
|
|
||||||
@ -169,7 +170,7 @@ fun YearGridView(
|
|||||||
titleLayouts = titleLayouts,
|
titleLayouts = titleLayouts,
|
||||||
weekdayLayouts = weekdayLayouts,
|
weekdayLayouts = weekdayLayouts,
|
||||||
onClick = { onMonthClick(month) },
|
onClick = { onMonthClick(month) },
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f).then(monthModifier(month))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user