feat: 转场动画优化 & 任务界面 MD3E 适配 & 待办卡片样式更新
This commit is contained in:
parent
2b28b446eb
commit
5b87a17a82
8 changed files with 182 additions and 93 deletions
|
|
@ -38,7 +38,7 @@ android {
|
|||
applicationId = "cn.super12138.todo"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 950
|
||||
versionCode = 951
|
||||
versionName = "2.3.3"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ object TodoDefaults {
|
|||
/**
|
||||
* 待办卡片默认高度
|
||||
*/
|
||||
val toDoCardHeight = 80.dp
|
||||
val toDoCardHeight = 86.dp
|
||||
|
||||
/**
|
||||
* 设置项水平边距
|
||||
|
|
|
|||
|
|
@ -2,11 +2,6 @@ package cn.super12138.todo.ui.navigation
|
|||
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.animation.SharedTransitionLayout
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.animation.unveilIn
|
||||
import androidx.compose.animation.veilOut
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -17,8 +12,13 @@ import cn.super12138.todo.ui.pages.editor.TodoAddPage
|
|||
import cn.super12138.todo.ui.pages.editor.TodoEditPage
|
||||
import cn.super12138.todo.ui.pages.overview.OverviewPage
|
||||
import cn.super12138.todo.ui.pages.tasks.TasksPage
|
||||
import cn.super12138.todo.ui.theme.fadeThrough
|
||||
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
||||
|
||||
/**
|
||||
* 来自:https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/transition/MaterialFadeThrough.java#L33
|
||||
*/
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
fun TopNavigation(
|
||||
|
|
@ -53,12 +53,12 @@ fun TopNavigation(
|
|||
* }
|
||||
*/
|
||||
|
||||
val veilColor = MaterialTheme.colorScheme.surfaceDim
|
||||
// val veilColor = MaterialTheme.colorScheme.surfaceDim
|
||||
SharedTransitionLayout {
|
||||
NavDisplay(
|
||||
backStack = backStack.backStack,
|
||||
onBack = ::onBack,
|
||||
transitionSpec = {
|
||||
/*transitionSpec = {
|
||||
fadeIn() togetherWith veilOut(targetColor = veilColor)
|
||||
},
|
||||
popTransitionSpec = {
|
||||
|
|
@ -66,6 +66,15 @@ fun TopNavigation(
|
|||
},
|
||||
predictivePopTransitionSpec = {
|
||||
unveilIn(initialColor = veilColor) togetherWith fadeOut()
|
||||
},*/
|
||||
transitionSpec = {
|
||||
fadeThrough()
|
||||
},
|
||||
popTransitionSpec = {
|
||||
fadeThrough()
|
||||
},
|
||||
predictivePopTransitionSpec = {
|
||||
fadeThrough()
|
||||
},
|
||||
entryProvider = entryProvider {
|
||||
entry<TodoScreen.Overview> {
|
||||
|
|
|
|||
|
|
@ -13,23 +13,20 @@ import androidx.compose.foundation.layout.Spacer
|
|||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation3.ui.LocalNavAnimatedContentScope
|
||||
|
|
@ -45,9 +42,9 @@ import cn.super12138.todo.ui.components.TopAppBarScaffold
|
|||
import cn.super12138.todo.ui.pages.editor.components.TodoCategoryChip
|
||||
import cn.super12138.todo.ui.pages.editor.components.TodoCategoryTextField
|
||||
import cn.super12138.todo.ui.pages.editor.components.TodoContentTextField
|
||||
import cn.super12138.todo.ui.pages.editor.components.TodoMarkAsCompletedCheckbox
|
||||
import cn.super12138.todo.ui.pages.editor.components.TodoPrioritySlider
|
||||
import cn.super12138.todo.ui.pages.editor.state.rememberEditorState
|
||||
import cn.super12138.todo.utils.VibrationUtils
|
||||
|
||||
@Composable
|
||||
fun SharedTransitionScope.TodoAddPage(
|
||||
|
|
@ -92,8 +89,6 @@ private fun TodoEditorPage(
|
|||
onNavigateUp: () -> Unit
|
||||
) {
|
||||
// TODO: 本页及其相关组件重组性能检查优化
|
||||
val view = LocalView.current
|
||||
|
||||
val uiState = rememberEditorState(initialTodo = toDo)
|
||||
|
||||
val originalCategories by DataStoreManager.categoriesFlow.collectAsState(initial = emptyList())
|
||||
|
|
@ -180,11 +175,11 @@ private fun TodoEditorPage(
|
|||
verticalArrangement = Arrangement.spacedBy(5.dp),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
item {
|
||||
item(key = 0) {
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.screenVerticalPadding))
|
||||
}
|
||||
|
||||
item {
|
||||
item(key=1) {
|
||||
TodoContentTextField(
|
||||
value = uiState.toDoContent,
|
||||
onValueChange = { uiState.toDoContent = it },
|
||||
|
|
@ -193,7 +188,7 @@ private fun TodoEditorPage(
|
|||
)
|
||||
}
|
||||
|
||||
item {
|
||||
item(key = 2) {
|
||||
Text(
|
||||
text = stringResource(R.string.label_category),
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
|
|
@ -222,7 +217,7 @@ private fun TodoEditorPage(
|
|||
}
|
||||
}
|
||||
|
||||
item {
|
||||
item (key = 3){
|
||||
Text(
|
||||
text = stringResource(R.string.label_priority),
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
|
|
@ -234,34 +229,22 @@ private fun TodoEditorPage(
|
|||
)
|
||||
}
|
||||
|
||||
item {
|
||||
item(key = 4) {
|
||||
if (toDo != null) {
|
||||
Text(
|
||||
text = stringResource(R.string.label_more),
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
TodoMarkAsCompletedCheckbox(
|
||||
checked = uiState.isCompleted,
|
||||
onCheckedChange = { uiState.isCompleted = it },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.tip_mark_completed),
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
modifier = Modifier.padding(end = 10.dp)
|
||||
)
|
||||
Switch(
|
||||
checked = uiState.isCompleted,
|
||||
onCheckedChange = {
|
||||
VibrationUtils.performHapticFeedback(view)
|
||||
uiState.isCompleted = it
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
item (key = 5){
|
||||
Spacer(modifier = Modifier.size(TodoDefaults.screenVerticalPadding))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
package cn.super12138.todo.ui.pages.editor.components
|
||||
|
||||
import android.view.HapticFeedbackConstants
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.selection.toggleable
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import cn.super12138.todo.R
|
||||
import cn.super12138.todo.utils.VibrationUtils
|
||||
|
||||
@Composable
|
||||
fun TodoMarkAsCompletedCheckbox(
|
||||
checked: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val view = LocalView.current
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = modifier
|
||||
.toggleable(
|
||||
value = checked,
|
||||
onValueChange = {
|
||||
VibrationUtils.performHapticFeedback(view, HapticFeedbackConstants.LONG_PRESS)
|
||||
onCheckedChange(it)
|
||||
},
|
||||
role = Role.Checkbox,
|
||||
indication = null,
|
||||
interactionSource = interactionSource,
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.tip_mark_completed),
|
||||
style = MaterialTheme.typography.labelLarge
|
||||
)
|
||||
|
||||
Checkbox(
|
||||
checked = checked,
|
||||
onCheckedChange = {
|
||||
VibrationUtils.performHapticFeedback(view, HapticFeedbackConstants.LONG_PRESS)
|
||||
onCheckedChange(it)
|
||||
},
|
||||
interactionSource = interactionSource
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
|
|
@ -27,7 +27,6 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation3.ui.LocalNavAnimatedContentScope
|
||||
import cn.super12138.todo.R
|
||||
import cn.super12138.todo.constants.Constants
|
||||
|
|
@ -103,7 +102,7 @@ fun SharedTransitionScope.TasksPage(
|
|||
) {
|
||||
LazyColumn(
|
||||
state = listState,
|
||||
verticalArrangement = Arrangement.spacedBy(5.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(TodoDefaults.settingsItemPadding),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
item {
|
||||
|
|
@ -120,32 +119,34 @@ fun SharedTransitionScope.TasksPage(
|
|||
)
|
||||
}
|
||||
} else {
|
||||
items(
|
||||
itemsIndexed(
|
||||
items = filteredTodoList,
|
||||
key = { it.id }
|
||||
) {
|
||||
key = { _, task -> task.id }
|
||||
) { index, task ->
|
||||
TodoCard(
|
||||
// id = item.id,
|
||||
content = it.content,
|
||||
category = it.category,
|
||||
completed = it.isCompleted,
|
||||
priority = Priority.fromFloat(it.priority),
|
||||
selected = selectedTodoIds.contains(it.id),
|
||||
content = task.content,
|
||||
category = task.category,
|
||||
completed = task.isCompleted,
|
||||
priority = Priority.fromFloat(task.priority),
|
||||
selected = selectedTodoIds.contains(task.id),
|
||||
onCardClick = {
|
||||
if (inSelectedMode) {
|
||||
viewModel.toggleTodoSelection(it)
|
||||
viewModel.toggleTodoSelection(task)
|
||||
} else {
|
||||
toTodoEditPage(it)
|
||||
toTodoEditPage(task)
|
||||
}
|
||||
},
|
||||
onCardLongClick = { viewModel.toggleTodoSelection(it) },
|
||||
onCardLongClick = { viewModel.toggleTodoSelection(task) },
|
||||
onChecked = {
|
||||
viewModel.updateTodo(it.copy(isCompleted = true))
|
||||
viewModel.updateTodo(task.copy(isCompleted = true))
|
||||
viewModel.playConfetti()
|
||||
},
|
||||
topRounded = index == 0,
|
||||
bottomRounded = index == filteredTodoList.size - 1,
|
||||
modifier = Modifier
|
||||
.sharedBounds(
|
||||
sharedContentState = rememberSharedContentState(key = "${Constants.KEY_TODO_ITEM_TRANSITION}_${it.id}"),
|
||||
sharedContentState = rememberSharedContentState(key = "${Constants.KEY_TODO_ITEM_TRANSITION}_${task.id}"),
|
||||
animatedVisibilityScope = LocalNavAnimatedContentScope.current
|
||||
)
|
||||
.animateItem(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package cn.super12138.todo.ui.pages.tasks.components
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.expandHorizontally
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
|
|
@ -17,10 +18,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.CornerBasedShape
|
||||
import androidx.compose.material3.Badge
|
||||
import androidx.compose.material3.BadgedBox
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
|
|
@ -28,6 +27,7 @@ import androidx.compose.material3.MaterialTheme
|
|||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.contentColorFor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
|
|
@ -42,6 +42,7 @@ import cn.super12138.todo.logic.model.Priority
|
|||
import cn.super12138.todo.ui.TodoDefaults
|
||||
import cn.super12138.todo.utils.VibrationUtils
|
||||
import cn.super12138.todo.utils.containerColor
|
||||
import cn.super12138.todo.utils.getPartialRoundedShape
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
|
|
@ -55,19 +56,22 @@ fun TodoCard(
|
|||
selected: Boolean,
|
||||
onCardClick: () -> Unit = {},
|
||||
onCardLongClick: () -> Unit = {},
|
||||
onChecked: () -> Unit = {}
|
||||
onChecked: () -> Unit = {},
|
||||
shape: CornerBasedShape = TodoDefaults.SettingsItemDefaultShape,
|
||||
roundedShape: CornerBasedShape = TodoDefaults.SettingsItemRoundedShape,
|
||||
topRounded: Boolean = false,
|
||||
bottomRounded: Boolean = false
|
||||
) {
|
||||
val view = LocalView.current
|
||||
Card(
|
||||
colors = CardDefaults.cardColors(containerColor = TodoDefaults.ContainerColor),
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.height(TodoDefaults.toDoCardHeight)
|
||||
) {
|
||||
// TODO: 滑动删除
|
||||
val animatedContainerColor by animateColorAsState(if (selected) MaterialTheme.colorScheme.secondaryContainer else TodoDefaults.ContainerColor)
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.height(TodoDefaults.toDoCardHeight)
|
||||
.clip(shape.getPartialRoundedShape(topRounded, bottomRounded, roundedShape))
|
||||
.combinedClickable(
|
||||
onClick = {
|
||||
VibrationUtils.performHapticFeedback(view)
|
||||
|
|
@ -77,7 +81,8 @@ fun TodoCard(
|
|||
// 因为 combinedClickable 在更新的 Compose 里已经处理好了触感反馈
|
||||
onLongClick = onCardLongClick
|
||||
)
|
||||
.padding(horizontal = 15.dp)
|
||||
.background(animatedContainerColor)
|
||||
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = selected,
|
||||
|
|
@ -104,40 +109,42 @@ fun TodoCard(
|
|||
}
|
||||
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
verticalArrangement = Arrangement.spacedBy(
|
||||
space = 5.dp,
|
||||
alignment = Alignment.CenterVertically
|
||||
),
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
BadgedBox(
|
||||
badge = {
|
||||
Badge(
|
||||
containerColor = priority.containerColor(),
|
||||
modifier = Modifier.padding(start = 5.dp)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(priority.nameRes),
|
||||
textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None,
|
||||
)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = content,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None,
|
||||
modifier = Modifier.basicMarquee() // TODO: 后续评估性能影响
|
||||
)
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(5.dp)
|
||||
) {
|
||||
Badge(containerColor = MaterialTheme.colorScheme.primary) {
|
||||
Text(
|
||||
text = category.ifEmpty { stringResource(R.string.tip_default_category) },
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None,
|
||||
maxLines = 1
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = content,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
text = stringResource(priority.nameRes),
|
||||
style = MaterialTheme.typography.labelMedium.copy(priority.containerColor()),
|
||||
textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None,
|
||||
modifier = Modifier.basicMarquee() // TODO: 后续评估性能影响
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = category.ifEmpty { stringResource(R.string.tip_default_category) },
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None,
|
||||
maxLines = 1
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility(!selected && !completed) {
|
||||
|
|
@ -172,7 +179,7 @@ fun TodoCard(
|
|||
)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import androidx.compose.animation.core.LinearOutSlowInEasing
|
|||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.scaleIn
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
|
||||
|
|
@ -17,6 +18,8 @@ import androidx.compose.animation.slideOutHorizontally
|
|||
*/
|
||||
|
||||
private const val ProgressThreshold = 0.35f
|
||||
private const val DEFAULT_START_SCALE = 0.95f //0.92f
|
||||
private const val THRESHOLD_ALPHA = 0.5f
|
||||
|
||||
private val Int.ForOutgoing: Int
|
||||
get() = (this * ProgressThreshold).toInt()
|
||||
|
|
@ -84,4 +87,31 @@ fun materialSharedAxisXOut(
|
|||
delayMillis = 0,
|
||||
easing = FastOutLinearInEasing
|
||||
)
|
||||
)
|
||||
|
||||
fun fadeThrough(
|
||||
durationMillis: Int = 200,
|
||||
): ContentTransform = ContentTransform(
|
||||
fadeThroughIn(durationMillis = durationMillis),
|
||||
fadeThroughOut(durationMillis = durationMillis)
|
||||
)
|
||||
|
||||
fun fadeThroughIn(
|
||||
durationMillis: Int = DefaultMotionDuration,
|
||||
): EnterTransition =
|
||||
fadeIn(
|
||||
animationSpec = tween(durationMillis),
|
||||
initialAlpha = THRESHOLD_ALPHA
|
||||
) + scaleIn(
|
||||
animationSpec = tween(durationMillis),
|
||||
initialScale = DEFAULT_START_SCALE
|
||||
)
|
||||
|
||||
fun fadeThroughOut(
|
||||
durationMillis: Int = DefaultMotionDuration,
|
||||
): ExitTransition = fadeOut(
|
||||
animationSpec = tween(
|
||||
durationMillis = durationMillis,
|
||||
easing = FastOutLinearInEasing
|
||||
)
|
||||
)
|
||||
Loading…
Reference in a new issue