diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8f362ab..5d80297 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -38,7 +38,7 @@ android { applicationId = "cn.super12138.todo" minSdk = 24 targetSdk = 36 - versionCode = 985 + versionCode = 986 versionName = "2.3.3" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/editor/TodoEditorPage.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/editor/TodoEditorPage.kt index b6e0686..fe18201 100644 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/editor/TodoEditorPage.kt +++ b/app/src/main/kotlin/cn/super12138/todo/ui/pages/editor/TodoEditorPage.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -85,6 +86,7 @@ fun SharedTransitionScope.TodoEditPage( onNavigateUp = onNavigateUp ) +@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun SharedTransitionScope.TodoEditorPage( modifier: Modifier = Modifier, @@ -210,8 +212,12 @@ fun SharedTransitionScope.TodoEditorPage( AnimatedVisibility( visible = isCustomCategory, - enter = fadeIn() + expandVertically(), - exit = fadeOut() + shrinkVertically() + enter = fadeIn(MaterialTheme.motionScheme.defaultEffectsSpec()) + expandVertically( + MaterialTheme.motionScheme.defaultEffectsSpec() + ), + exit = fadeOut(MaterialTheme.motionScheme.defaultEffectsSpec()) + shrinkVertically( + MaterialTheme.motionScheme.defaultEffectsSpec() + ) ) { TodoCategoryTextField( value = uiState.categoryContent, diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/tasks/components/TodoTopAppBar.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/tasks/components/TodoTopAppBar.kt index 5049a43..ad944a2 100644 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/tasks/components/TodoTopAppBar.kt +++ b/app/src/main/kotlin/cn/super12138/todo/ui/pages/tasks/components/TodoTopAppBar.kt @@ -2,16 +2,16 @@ package cn.super12138.todo.ui.pages.tasks.components import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ContentTransform import androidx.compose.animation.animateColorAsState -import androidx.compose.animation.core.tween import androidx.compose.animation.expandIn import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.scaleIn import androidx.compose.animation.shrinkOut -import androidx.compose.animation.togetherWith import androidx.compose.foundation.layout.Row import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -22,9 +22,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -34,7 +35,7 @@ import cn.super12138.todo.R import cn.super12138.todo.ui.TodoDefaults import cn.super12138.todo.utils.VibrationUtils -@OptIn(ExperimentalMaterial3Api::class) +@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable fun TodoTopAppBar( selectedTodoIds: List, @@ -44,8 +45,32 @@ fun TodoTopAppBar( onDeleteSelectedTodo: () -> Unit, modifier: Modifier = Modifier ) { + val navIconEnterTransition = fadeIn( + animationSpec = MaterialTheme.motionScheme.defaultEffectsSpec() + ) + expandIn( + animationSpec = MaterialTheme.motionScheme.defaultSpatialSpec(), + expandFrom = Alignment.CenterStart + ) + val navIconExitTransition = fadeOut( + animationSpec = MaterialTheme.motionScheme.defaultEffectsSpec() + ) + shrinkOut( + animationSpec = MaterialTheme.motionScheme.defaultSpatialSpec(), + shrinkTowards = Alignment.CenterStart + ) + val enterTransition = fadeIn(MaterialTheme.motionScheme.defaultEffectsSpec()) + + scaleIn( + animationSpec = MaterialTheme.motionScheme.defaultSpatialSpec(), + initialScale = 0.92f + ) + val exitTransition = fadeOut(MaterialTheme.motionScheme.defaultEffectsSpec()) + val titleTransition = ContentTransform( + targetContentEnter = enterTransition, + initialContentExit = exitTransition + ) + val view = LocalView.current - val animatedTopAppBarColors by animateColorAsState( + val animatedContainerColor by animateColorAsState( + animationSpec = MaterialTheme.motionScheme.defaultEffectsSpec(), targetValue = if (selectedMode) { MaterialTheme.colorScheme.surfaceContainerHighest } else { @@ -57,8 +82,8 @@ fun TodoTopAppBar( navigationIcon = { AnimatedVisibility( visible = selectedMode, - enter = fadeIn() + expandIn(expandFrom = Alignment.CenterStart), - exit = shrinkOut(shrinkTowards = Alignment.CenterStart) + fadeOut() + enter = navIconEnterTransition, + exit = navIconExitTransition ) { IconButton( onClick = { @@ -76,14 +101,7 @@ fun TodoTopAppBar( title = { AnimatedContent( targetState = !selectedMode, - transitionSpec = { - ( - fadeIn(animationSpec = tween(100)) + - scaleIn(initialScale = 0.92f) - ).togetherWith( - fadeOut(animationSpec = tween(100)) - ) - } + transitionSpec = { titleTransition } ) { if (it) { Text( @@ -104,7 +122,11 @@ fun TodoTopAppBar( } }, actions = { - AnimatedVisibility(visible = selectedMode) { + AnimatedVisibility( + visible = selectedMode, + enter = enterTransition, + exit = exitTransition + ) { Row { IconButton( onClick = { @@ -132,21 +154,21 @@ fun TodoTopAppBar( } }, - colors = TopAppBarDefaults.topAppBarColors().copy( - containerColor = animatedTopAppBarColors - ), - modifier = modifier + colors = TopAppBarDefaults.topAppBarColors().copy(containerColor = Color.Transparent), + modifier = modifier.drawBehind { + drawRect(animatedContainerColor) + } ) } @Preview(locale = "zh-rCN", showBackground = true) @Composable private fun TodoTopAppBarPreview() { - var selectedMode by remember { mutableStateOf(false) } + val selectedMode = remember { mutableStateOf(false) } TodoTopAppBar( selectedTodoIds = (1..10).toList(), - selectedMode = selectedMode, - onCancelSelect = { selectedMode = !selectedMode }, + selectedMode = selectedMode.value, + onCancelSelect = { selectedMode.value = !selectedMode.value }, onSelectAll = { }, onDeleteSelectedTodo = { } )