feat: 适配 MD3E 部分动画

This commit is contained in:
Super12138 2025-11-22 20:25:57 +08:00
parent 3487c64fe5
commit 63a7a83071
6 changed files with 52 additions and 39 deletions

View file

@ -10,7 +10,7 @@ enum class Priority(val value: Float) {
NotImportant(-1f), NotImportant(-1f),
NotUrgent(-2f); NotUrgent(-2f);
fun getDisplayName(context: Context): String { fun displayName(context: Context): String {
val resId = when (this) { val resId = when (this) {
Urgent -> R.string.priority_urgent Urgent -> R.string.priority_urgent
Important -> R.string.priority_important Important -> R.string.priority_important

View file

@ -35,7 +35,7 @@ fun TodoPrioritySlider(
val view = LocalView.current val view = LocalView.current
val context = LocalContext.current val context = LocalContext.current
val priorityName = remember { Priority.entries.map { it.getDisplayName(context) } } val priorityName = remember { Priority.entries.map { it.displayName(context) } }
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
Slider( Slider(

View file

@ -164,8 +164,6 @@ fun MainPage(
}, },
selectedTodoIds = selectedTodoIds, selectedTodoIds = selectedTodoIds,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
// sharedTransitionScope = sharedTransitionScope,
// animatedVisibilityScope = animatedVisibilityScope,
) )
} }
/*}*/ /*}*/

View file

@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -21,7 +22,7 @@ import cn.super12138.todo.ui.TodoDefaults
import cn.super12138.todo.ui.components.LazyColumnCustomScrollBar import cn.super12138.todo.ui.components.LazyColumnCustomScrollBar
import cn.super12138.todo.ui.pages.main.components.TodoCard import cn.super12138.todo.ui.pages.main.components.TodoCard
@OptIn(ExperimentalSharedTransitionApi::class) @OptIn(ExperimentalSharedTransitionApi::class, ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
fun ManagerFragment( fun ManagerFragment(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -30,9 +31,7 @@ fun ManagerFragment(
onItemClick: (TodoEntity) -> Unit = {}, onItemClick: (TodoEntity) -> Unit = {},
onItemLongClick: (TodoEntity) -> Unit = {}, onItemLongClick: (TodoEntity) -> Unit = {},
onItemChecked: (TodoEntity) -> Unit = {}, onItemChecked: (TodoEntity) -> Unit = {},
selectedTodoIds: List<Int>, selectedTodoIds: List<Int>
// sharedTransitionScope: SharedTransitionScope,
// animatedVisibilityScope: AnimatedVisibilityScope
) { ) {
LazyColumnCustomScrollBar( LazyColumnCustomScrollBar(
state = state, state = state,
@ -79,11 +78,13 @@ fun ManagerFragment(
onCardClick = { onItemClick(item) }, onCardClick = { onItemClick(item) },
onCardLongClick = { onItemLongClick(item) }, onCardLongClick = { onItemLongClick(item) },
onChecked = { onItemChecked(item) }, onChecked = { onItemChecked(item) },
// sharedTransitionScope = sharedTransitionScope,
// animatedVisibilityScope = animatedVisibilityScope,
modifier = Modifier modifier = Modifier
.padding(vertical = 5.dp) .padding(vertical = 5.dp)
.animateItem() // TODO: 设置动画时间 .animateItem(
fadeInSpec = MaterialTheme.motionScheme.defaultEffectsSpec(),
placementSpec = MaterialTheme.motionScheme.defaultSpatialSpec(),
fadeOutSpec = MaterialTheme.motionScheme.fastEffectsSpec()
)
) )
} }
} }

View file

@ -2,6 +2,10 @@ package cn.super12138.todo.ui.pages.main.components
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalSharedTransitionApi import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.expandHorizontally
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkHorizontally
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee import androidx.compose.foundation.basicMarquee
@ -18,6 +22,7 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Badge import androidx.compose.material3.Badge
import androidx.compose.material3.BadgedBox import androidx.compose.material3.BadgedBox
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -38,8 +43,12 @@ import cn.super12138.todo.R
import cn.super12138.todo.logic.model.Priority import cn.super12138.todo.logic.model.Priority
import cn.super12138.todo.ui.TodoDefaults import cn.super12138.todo.ui.TodoDefaults
import cn.super12138.todo.utils.VibrationUtils import cn.super12138.todo.utils.VibrationUtils
import cn.super12138.todo.utils.containerColor
@OptIn(ExperimentalFoundationApi::class, ExperimentalSharedTransitionApi::class) @OptIn(
ExperimentalFoundationApi::class, ExperimentalSharedTransitionApi::class,
ExperimentalMaterial3ExpressiveApi::class
)
@Composable @Composable
fun TodoCard( fun TodoCard(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -51,9 +60,7 @@ fun TodoCard(
selected: Boolean, selected: Boolean,
onCardClick: () -> Unit = {}, onCardClick: () -> Unit = {},
onCardLongClick: () -> Unit = {}, onCardLongClick: () -> Unit = {},
onChecked: () -> Unit = {}, onChecked: () -> Unit = {}
// sharedTransitionScope: SharedTransitionScope,
// animatedVisibilityScope: AnimatedVisibilityScope
) { ) {
val view = LocalView.current val view = LocalView.current
val context = LocalContext.current val context = LocalContext.current
@ -77,7 +84,15 @@ fun TodoCard(
) )
.padding(horizontal = 15.dp) .padding(horizontal = 15.dp)
) { ) {
AnimatedVisibility(selected) { AnimatedVisibility(
visible = selected,
enter = fadeIn(MaterialTheme.motionScheme.fastSpatialSpec()) + expandHorizontally(
MaterialTheme.motionScheme.fastSpatialSpec()
),
exit = fadeOut(MaterialTheme.motionScheme.fastSpatialSpec()) + shrinkHorizontally(
MaterialTheme.motionScheme.fastSpatialSpec()
)
) {
Box( Box(
Modifier Modifier
.padding(end = 15.dp) .padding(end = 15.dp)
@ -102,51 +117,32 @@ fun TodoCard(
BadgedBox( BadgedBox(
badge = { badge = {
Badge( Badge(
containerColor = when (priority) { containerColor = priority.containerColor(),
Priority.NotUrgent -> MaterialTheme.colorScheme.surfaceContainerHighest
Priority.NotImportant -> MaterialTheme.colorScheme.surfaceContainerHighest
Priority.Default -> MaterialTheme.colorScheme.secondary
Priority.Important -> MaterialTheme.colorScheme.tertiary
Priority.Urgent -> MaterialTheme.colorScheme.error
},
modifier = Modifier.padding(start = 5.dp) modifier = Modifier.padding(start = 5.dp)
) { ) {
Text( Text(
text = priority.getDisplayName(context), text = priority.displayName(context),
textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None, textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None,
) )
} }
} }
) { ) {
// with(sharedTransitionScope) {
Text( Text(
text = content, text = content,
style = MaterialTheme.typography.titleLarge, style = MaterialTheme.typography.titleLarge,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None, textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None,
modifier = Modifier modifier = Modifier.basicMarquee() // TODO: 后续评估性能影响
/*.sharedBounds(
sharedContentState = rememberSharedContentState("${Constants.KEY_TODO_CONTENT_TRANSITION}_$id"),
animatedVisibilityScope = animatedVisibilityScope
)*/
.basicMarquee() // TODO: 后续评估性能影响
) )
// }
} }
// with(sharedTransitionScope) {
Text( Text(
text = category.ifEmpty { stringResource(R.string.tip_default_category) }, text = category.ifEmpty { stringResource(R.string.tip_default_category) },
style = MaterialTheme.typography.labelMedium, style = MaterialTheme.typography.labelMedium,
textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None, textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None,
maxLines = 1, maxLines = 1
/*modifier = Modifier.sharedBounds(
sharedContentState = rememberSharedContentState("${Constants.KEY_TODO_CATEGORY_TRANSITION}_$id"),
animatedVisibilityScope = animatedVisibilityScope
)*/
) )
// }
} }
AnimatedVisibility(!selected && !completed) { AnimatedVisibility(!selected && !completed) {

View file

@ -0,0 +1,18 @@
package cn.super12138.todo.utils
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.Color
import cn.super12138.todo.logic.model.Priority
@Composable
@Stable
fun Priority.containerColor(): Color =
when (this) {
Priority.NotUrgent -> MaterialTheme.colorScheme.surfaceContainerHighest
Priority.NotImportant -> MaterialTheme.colorScheme.surfaceContainerHighest
Priority.Default -> MaterialTheme.colorScheme.secondary
Priority.Important -> MaterialTheme.colorScheme.tertiary
Priority.Urgent -> MaterialTheme.colorScheme.error
}