refactor: 对组件进行 Material 3 Expressive 适配

This commit is contained in:
Super12138 2025-10-25 16:47:11 +08:00
parent bc189c9b9c
commit 96fdb86e91
11 changed files with 177 additions and 85 deletions

View file

@ -6,14 +6,19 @@ import cn.super12138.todo.R
enum class SortingMethod(val id: Int) { enum class SortingMethod(val id: Int) {
// 按添加先后顺序 // 按添加先后顺序
Sequential(1), Sequential(1),
// 按学科 // 按学科
Category(2), Category(2),
// 按优先级 // 按优先级
Priority(3), Priority(3),
// 按完成情况 // 按完成情况
Completion(4), Completion(4),
// 按字母升序 // 按字母升序
AlphabeticalAscending(5), AlphabeticalAscending(5),
// 按字母降序 // 按字母降序
AlphabeticalDescending(6); AlphabeticalDescending(6);

View file

@ -22,4 +22,24 @@ object TodoDefaults {
* 设置项垂直边距 * 设置项垂直边距
*/ */
val settingsItemVerticalPadding = 20.dp val settingsItemVerticalPadding = 20.dp
/**
* 待办进度条粗度
*/
val trackThickness = 7.0.dp
/**
* 待办进度条波长
*/
val waveLength = 35.dp
/**
* 待办进度条波速
*/
val waveSpeed = 3.dp
/**
* 待办进度条波幅
*/
const val waveAmplitude = 0.6f
} }

View file

@ -1,11 +1,5 @@
package cn.super12138.todo.ui.components package cn.super12138.todo.ui.components
import android.util.Log
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandIn
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkOut
import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
@ -18,19 +12,16 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import cn.super12138.todo.R import cn.super12138.todo.R
import cn.super12138.todo.utils.VibrationUtils import cn.super12138.todo.utils.VibrationUtils
import kotlin.math.log
/** /**
* 部分参考https://github.com/Rhythamtech/FilterChipGroup-Compose-Android/blob/main/FilterChipGroup.kt * 部分参考https://github.com/Rhythamtech/FilterChipGroup-Compose-Android/blob/main/FilterChipGroup.kt
@ -75,20 +66,19 @@ private fun FilterChipItem(
FilterChip( FilterChip(
selected = selected, selected = selected,
onClick = onClick, onClick = onClick,
leadingIcon = {
AnimatedVisibility(
visible = selected,
enter = expandIn(expandFrom = Alignment.CenterStart) + fadeIn(),
exit = shrinkOut(shrinkTowards = Alignment.CenterStart) + fadeOut()
) {
Icon(
imageVector = Icons.Outlined.Check,
contentDescription = stringResource(R.string.tip_select_this),
modifier = Modifier.size(FilterChipDefaults.IconSize)
)
}
},
label = { Text(text) }, label = { Text(text) },
leadingIcon =
if (selected) {
{
Icon(
imageVector = Icons.Outlined.Check,
contentDescription = stringResource(R.string.tip_select_this),
modifier = Modifier.size(FilterChipDefaults.IconSize)
)
}
} else {
null
},
modifier = modifier.padding(end = 10.dp) modifier = modifier.padding(end = 10.dp)
) )
} }

View file

@ -6,6 +6,8 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ErrorOutline import androidx.compose.material.icons.outlined.ErrorOutline
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -50,6 +52,7 @@ fun ConfirmDialog(
) )
} }
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
fun BasicDialog( fun BasicDialog(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -83,7 +86,8 @@ fun BasicDialog(
onClick = { onClick = {
VibrationUtils.performHapticFeedback(view) VibrationUtils.performHapticFeedback(view)
onConfirm() onConfirm()
} },
shapes = ButtonDefaults.shapes()
) { ) {
Text(confirmButton) Text(confirmButton)
} }
@ -94,7 +98,8 @@ fun BasicDialog(
onClick = { onClick = {
VibrationUtils.performHapticFeedback(view) VibrationUtils.performHapticFeedback(view)
onDismiss() onDismiss()
} },
shapes = ButtonDefaults.shapes()
) { ) {
Text(it) Text(it)
} }

View file

@ -1,39 +1,47 @@
package cn.super12138.todo.ui.components package cn.super12138.todo.ui.components
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularWavyProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.ProgressIndicatorDefaults import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.WavyProgressIndicatorDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
fun AnimatedCircularProgressIndicator( fun AnimatedCircularWavyProgressIndicator(
progress: Float, progress: Float,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
color: Color = ProgressIndicatorDefaults.circularColor, color: Color = WavyProgressIndicatorDefaults.indicatorColor,
strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth, trackColor: Color = WavyProgressIndicatorDefaults.trackColor,
trackColor: Color = ProgressIndicatorDefaults.circularDeterminateTrackColor, stroke: Stroke = WavyProgressIndicatorDefaults.circularIndicatorStroke,
strokeCap: StrokeCap = ProgressIndicatorDefaults.CircularDeterminateStrokeCap, trackStroke: Stroke = WavyProgressIndicatorDefaults.circularTrackStroke,
gapSize: Dp = ProgressIndicatorDefaults.CircularIndicatorTrackGapSize gapSize: Dp = WavyProgressIndicatorDefaults.CircularIndicatorTrackGapSize,
amplitude: (progress: Float) -> Float = WavyProgressIndicatorDefaults.indicatorAmplitude,
wavelength: Dp = WavyProgressIndicatorDefaults.CircularWavelength,
waveSpeed: Dp = wavelength,
) { ) {
val animatedProgress by animateFloatAsState( val animatedProgress by animateFloatAsState(
targetValue = progress, targetValue = progress,
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
) )
CircularProgressIndicator( CircularWavyProgressIndicator(
progress = { animatedProgress }, progress = { animatedProgress },
modifier = modifier, modifier = modifier,
color = color, color = color,
strokeWidth = strokeWidth,
trackColor = trackColor, trackColor = trackColor,
strokeCap = strokeCap, stroke = stroke,
gapSize = gapSize trackStroke = trackStroke,
gapSize = gapSize,
amplitude = amplitude,
wavelength = wavelength,
waveSpeed = waveSpeed,
) )
} }

View file

@ -13,9 +13,12 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ExitToApp import androidx.compose.material.icons.automirrored.outlined.ExitToApp
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon
import androidx.compose.material3.LargeTopAppBar import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SmallExtendedFloatingActionButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -40,12 +43,11 @@ import cn.super12138.todo.ui.activities.CrashActivity.Companion.BRAND_PREFIX
import cn.super12138.todo.ui.activities.CrashActivity.Companion.CRASH_TIME_PREFIX import cn.super12138.todo.ui.activities.CrashActivity.Companion.CRASH_TIME_PREFIX
import cn.super12138.todo.ui.activities.CrashActivity.Companion.DEVICE_SDK_PREFIX import cn.super12138.todo.ui.activities.CrashActivity.Companion.DEVICE_SDK_PREFIX
import cn.super12138.todo.ui.activities.CrashActivity.Companion.MODEL_PREFIX import cn.super12138.todo.ui.activities.CrashActivity.Companion.MODEL_PREFIX
import cn.super12138.todo.ui.components.AnimatedExtendedFloatingActionButton
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
fun CrashPage( fun CrashPage(
crashLog: String, crashLog: String,
@ -77,11 +79,16 @@ fun CrashPage(
) )
}, },
floatingActionButton = { floatingActionButton = {
AnimatedExtendedFloatingActionButton( SmallExtendedFloatingActionButton(
onClick = exitApp, text = { Text(stringResource(R.string.action_exit_app)) },
icon = Icons.AutoMirrored.Outlined.ExitToApp, icon = {
text = stringResource(R.string.action_exit_app), Icon(
expanded = isExpanded imageVector = Icons.AutoMirrored.Outlined.ExitToApp,
contentDescription = null
)
},
expanded = isExpanded,
onClick = exitApp
) )
}, },
contentWindowInsets = WindowInsets(0, 0, 0, 0) contentWindowInsets = WindowInsets(0, 0, 0, 0)

View file

@ -23,7 +23,10 @@ import androidx.compose.material.icons.automirrored.outlined.Undo
import androidx.compose.material.icons.outlined.Delete import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.Save import androidx.compose.material.icons.outlined.Save
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SmallExtendedFloatingActionButton
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
@ -45,7 +48,6 @@ import cn.super12138.todo.constants.Constants
import cn.super12138.todo.logic.database.TodoEntity import cn.super12138.todo.logic.database.TodoEntity
import cn.super12138.todo.logic.datastore.DataStoreManager import cn.super12138.todo.logic.datastore.DataStoreManager
import cn.super12138.todo.ui.TodoDefaults import cn.super12138.todo.ui.TodoDefaults
import cn.super12138.todo.ui.components.AnimatedExtendedFloatingActionButton
import cn.super12138.todo.ui.components.ChipItem import cn.super12138.todo.ui.components.ChipItem
import cn.super12138.todo.ui.components.ConfirmDialog import cn.super12138.todo.ui.components.ConfirmDialog
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
@ -56,7 +58,10 @@ import cn.super12138.todo.ui.pages.editor.components.TodoPrioritySlider
import cn.super12138.todo.ui.pages.editor.state.rememberEditorState import cn.super12138.todo.ui.pages.editor.state.rememberEditorState
import cn.super12138.todo.utils.VibrationUtils import cn.super12138.todo.utils.VibrationUtils
@OptIn(ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class) @OptIn(
ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class,
ExperimentalMaterial3ExpressiveApi::class
)
@Composable @Composable
fun TodoEditorPage( fun TodoEditorPage(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -119,22 +124,32 @@ fun TodoEditorPage(
with(sharedTransitionScope) { with(sharedTransitionScope) {
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) { Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
if (toDo !== null) { if (toDo !== null) {
AnimatedExtendedFloatingActionButton( SmallExtendedFloatingActionButton(
icon = Icons.Outlined.Delete, text = { Text(stringResource(R.string.action_delete)) },
text = stringResource(R.string.action_delete), icon = {
Icon(
imageVector = Icons.Outlined.Delete,
contentDescription = null
)
},
expanded = true, expanded = true,
containerColor = MaterialTheme.colorScheme.errorContainer, containerColor = MaterialTheme.colorScheme.errorContainer,
onClick = { uiState.showDeleteConfirmDialog = true }, onClick = { uiState.showDeleteConfirmDialog = true },
modifier = Modifier.imePadding() modifier = Modifier.imePadding()
) )
} }
AnimatedExtendedFloatingActionButton( SmallExtendedFloatingActionButton(
icon = Icons.Outlined.Save, text = { Text(stringResource(R.string.action_save)) },
text = stringResource(R.string.action_save), icon = {
Icon(
imageVector = Icons.Outlined.Save,
contentDescription = null
)
},
expanded = true, expanded = true,
onClick = { onClick = {
if (uiState.setErrorIfNotValid()) { if (uiState.setErrorIfNotValid()) {
return@AnimatedExtendedFloatingActionButton return@SmallExtendedFloatingActionButton
} else { } else {
uiState.clearError() uiState.clearError()
val newTodo = TodoEntity( val newTodo = TodoEntity(

View file

@ -18,7 +18,11 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Add import androidx.compose.material.icons.outlined.Add
import androidx.compose.material.icons.outlined.Delete import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SmallExtendedFloatingActionButton
import androidx.compose.material3.Text
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@ -35,12 +39,11 @@ import cn.super12138.todo.R
import cn.super12138.todo.constants.Constants import cn.super12138.todo.constants.Constants
import cn.super12138.todo.logic.database.TodoEntity import cn.super12138.todo.logic.database.TodoEntity
import cn.super12138.todo.logic.datastore.DataStoreManager import cn.super12138.todo.logic.datastore.DataStoreManager
import cn.super12138.todo.ui.components.AnimatedExtendedFloatingActionButton
import cn.super12138.todo.ui.components.ConfirmDialog import cn.super12138.todo.ui.components.ConfirmDialog
import cn.super12138.todo.ui.pages.main.components.TodoTopAppBar import cn.super12138.todo.ui.pages.main.components.TodoTopAppBar
import cn.super12138.todo.ui.viewmodels.MainViewModel import cn.super12138.todo.ui.viewmodels.MainViewModel
@OptIn(ExperimentalSharedTransitionApi::class) @OptIn(ExperimentalSharedTransitionApi::class, ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
fun MainPage( fun MainPage(
viewModel: MainViewModel, viewModel: MainViewModel,
@ -65,6 +68,7 @@ fun MainPage(
val completedTasks by remember { derivedStateOf { toDoList.count { it.isCompleted } } } val completedTasks by remember { derivedStateOf { toDoList.count { it.isCompleted } } }
val filteredTodoList = val filteredTodoList =
if (showCompleted) toDoList else toDoList.filter { item -> !item.isCompleted } if (showCompleted) toDoList else toDoList.filter { item -> !item.isCompleted }
val expandedFab by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }
// 当按下返回键(或进行返回操作)时清空选择,仅在非选择模式下生效 // 当按下返回键(或进行返回操作)时清空选择,仅在非选择模式下生效
BackHandler(inSelectedMode) { viewModel.clearAllTodoSelection() } BackHandler(inSelectedMode) { viewModel.clearAllTodoSelection() }
@ -88,7 +92,7 @@ fun MainPage(
exit = shrinkOut() + fadeOut() exit = shrinkOut() + fadeOut()
) { ) {
// TODO: 修复在滑动列表时FAB位移导致的动画不连贯临时方案为底部加padding // TODO: 修复在滑动列表时FAB位移导致的动画不连贯临时方案为底部加padding
AnimatedExtendedFloatingActionButton( /*AnimatedExtendedFloatingActionButton(
icon = Icons.Outlined.Add, icon = Icons.Outlined.Add,
text = stringResource(R.string.action_add_task), text = stringResource(R.string.action_add_task),
expanded = true, expanded = true,
@ -100,6 +104,24 @@ fun MainPage(
sharedContentState = rememberSharedContentState(key = Constants.KEY_TODO_FAB_TRANSITION), sharedContentState = rememberSharedContentState(key = Constants.KEY_TODO_FAB_TRANSITION),
animatedVisibilityScope = animatedVisibilityScope animatedVisibilityScope = animatedVisibilityScope
) )
)*/
SmallExtendedFloatingActionButton(
text = { Text(stringResource(R.string.action_add_task)) },
icon = {
Icon(
imageVector = Icons.Outlined.Add,
contentDescription = null
)
},
expanded = expandedFab,
onClick = {
viewModel.setEditTodoItem(null) // 每次添加待办前清除上一次已选待办
toTodoEditPage()
},
modifier = Modifier.sharedElement(
sharedContentState = rememberSharedContentState(key = Constants.KEY_TODO_FAB_TRANSITION),
animatedVisibilityScope = animatedVisibilityScope
)
) )
} }
} }

View file

@ -10,14 +10,18 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import cn.super12138.todo.R import cn.super12138.todo.R
import cn.super12138.todo.ui.components.AnimatedCircularProgressIndicator import cn.super12138.todo.ui.TodoDefaults
import cn.super12138.todo.ui.components.AnimatedCircularWavyProgressIndicator
@Composable @Composable
fun ProgressFragment( fun ProgressFragment(
@ -25,6 +29,11 @@ fun ProgressFragment(
completedTasks: Int, completedTasks: Int,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val stroke = Stroke(
width = with(LocalDensity.current) { TodoDefaults.trackThickness.toPx() },
cap = StrokeCap.Round,
)
val context = LocalContext.current val context = LocalContext.current
val remainTasks = totalTasks - completedTasks val remainTasks = totalTasks - completedTasks
@ -39,10 +48,19 @@ fun ProgressFragment(
modifier = modifier, modifier = modifier,
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
AnimatedCircularProgressIndicator( AnimatedCircularWavyProgressIndicator(
progress = progress, progress = progress,
strokeWidth = 10.dp, stroke = stroke,
gapSize = 10.dp, trackStroke = stroke,
amplitude = { progress ->
if (progress <= 0.1f || progress >= 0.95f) {
0f
} else {
TodoDefaults.waveAmplitude
}
},
wavelength = TodoDefaults.waveLength,
waveSpeed = TodoDefaults.waveSpeed,
modifier = Modifier modifier = Modifier
.size(175.dp) .size(175.dp)
.clearAndSetSemantics {} .clearAndSetSemantics {}

View file

@ -120,33 +120,33 @@ fun TodoCard(
} }
) { ) {
// with(sharedTransitionScope) { // 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
/*.sharedBounds( /*.sharedBounds(
sharedContentState = rememberSharedContentState("${Constants.KEY_TODO_CONTENT_TRANSITION}_$id"), sharedContentState = rememberSharedContentState("${Constants.KEY_TODO_CONTENT_TRANSITION}_$id"),
animatedVisibilityScope = animatedVisibilityScope animatedVisibilityScope = animatedVisibilityScope
)*/ )*/
.basicMarquee() // TODO: 后续评估性能影响 .basicMarquee() // TODO: 后续评估性能影响
) )
// } // }
} }
// with(sharedTransitionScope) { // 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( /*modifier = Modifier.sharedBounds(
sharedContentState = rememberSharedContentState("${Constants.KEY_TODO_CATEGORY_TRANSITION}_$id"), sharedContentState = rememberSharedContentState("${Constants.KEY_TODO_CATEGORY_TRANSITION}_$id"),
animatedVisibilityScope = animatedVisibilityScope animatedVisibilityScope = animatedVisibilityScope
)*/ )*/
) )
// } // }
} }

View file

@ -2,11 +2,13 @@ package cn.super12138.todo.ui.theme
import android.os.Build import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.MaterialExpressiveTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.colorResource
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
fun ToDoTheme( fun ToDoTheme(
color: Color? = null, color: Color? = null,
@ -33,7 +35,7 @@ fun ToDoTheme(
contrastLevel = contrastLevel contrastLevel = contrastLevel
) )
MaterialTheme( MaterialExpressiveTheme(
colorScheme = colorScheme, colorScheme = colorScheme,
typography = Typography, typography = Typography,
content = content content = content