feat: 支持设置任务优先级
This commit is contained in:
parent
e962a9f361
commit
08d7706b15
11 changed files with 213 additions and 53 deletions
|
|
@ -9,5 +9,6 @@ data class TodoEntity(
|
||||||
@ColumnInfo(name = "content") val content: String,
|
@ColumnInfo(name = "content") val content: String,
|
||||||
@ColumnInfo(name = "subject") val subject: Int,
|
@ColumnInfo(name = "subject") val subject: Int,
|
||||||
@ColumnInfo(name = "completed") val isCompleted: Boolean = false,
|
@ColumnInfo(name = "completed") val isCompleted: Boolean = false,
|
||||||
|
@ColumnInfo(name = "priority") val priority: Float,
|
||||||
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Int = 0,
|
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Int = 0,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ fun FilterChipGroup(
|
||||||
label = {
|
label = {
|
||||||
Text(item)
|
Text(item)
|
||||||
},
|
},
|
||||||
modifier = Modifier.padding(horizontal = 5.dp)
|
modifier = Modifier.padding(end = 10.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@ import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.FloatingActionButtonDefaults
|
import androidx.compose.material3.FloatingActionButtonDefaults
|
||||||
import androidx.compose.material3.FloatingActionButtonElevation
|
import androidx.compose.material3.FloatingActionButtonElevation
|
||||||
|
import androidx.compose.material3.contentColorFor
|
||||||
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.Color
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -28,14 +30,18 @@ import androidx.compose.ui.unit.dp
|
||||||
fun AnimatedExtendedFloatingActionButton(
|
fun AnimatedExtendedFloatingActionButton(
|
||||||
icon: @Composable () -> Unit,
|
icon: @Composable () -> Unit,
|
||||||
text: @Composable () -> Unit,
|
text: @Composable () -> Unit,
|
||||||
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
|
|
||||||
expanded: Boolean,
|
expanded: Boolean,
|
||||||
|
containerColor: Color = FloatingActionButtonDefaults.containerColor,
|
||||||
|
contentColor: Color = contentColorFor(containerColor),
|
||||||
|
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
elevation = elevation,
|
elevation = elevation,
|
||||||
|
containerColor = containerColor,
|
||||||
|
contentColor = contentColor,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.exclude
|
||||||
|
import androidx.compose.foundation.layout.ime
|
||||||
import androidx.compose.foundation.layout.safeContent
|
import androidx.compose.foundation.layout.safeContent
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
|
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
|
||||||
|
|
@ -41,7 +43,7 @@ fun LargeTopAppBarScaffold(
|
||||||
snackbarHost: @Composable () -> Unit = {},
|
snackbarHost: @Composable () -> Unit = {},
|
||||||
floatingActionButton: @Composable () -> Unit = {},
|
floatingActionButton: @Composable () -> Unit = {},
|
||||||
floatingActionButtonPosition: FabPosition = FabPosition.End,
|
floatingActionButtonPosition: FabPosition = FabPosition.End,
|
||||||
contentWindowInsets: WindowInsets = WindowInsets.safeContent,
|
contentWindowInsets: WindowInsets = WindowInsets.safeContent.exclude(WindowInsets.ime),
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
content: @Composable (PaddingValues) -> Unit
|
content: @Composable (PaddingValues) -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
@ -62,6 +64,8 @@ fun LargeTopAppBarScaffold(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
|
floatingActionButton = floatingActionButton,
|
||||||
|
floatingActionButtonPosition = floatingActionButtonPosition,
|
||||||
contentWindowInsets = contentWindowInsets
|
contentWindowInsets = contentWindowInsets
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
Box { content(innerPadding) }
|
Box { content(innerPadding) }
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ fun TodoNavigation(
|
||||||
toDo = viewModel.selectedEditTodo,
|
toDo = viewModel.selectedEditTodo,
|
||||||
onSave = {
|
onSave = {
|
||||||
viewModel.addTodo(it)
|
viewModel.addTodo(it)
|
||||||
|
viewModel.setEditTodoItem(null)
|
||||||
navController.navigateUp()
|
navController.navigateUp()
|
||||||
},
|
},
|
||||||
onDelete = {
|
onDelete = {
|
||||||
|
|
@ -72,8 +73,8 @@ fun TodoNavigation(
|
||||||
navController.navigateUp()
|
navController.navigateUp()
|
||||||
},
|
},
|
||||||
onNavigateUp = {
|
onNavigateUp = {
|
||||||
viewModel.setEditTodoItem(null)
|
|
||||||
navController.navigateUp()
|
navController.navigateUp()
|
||||||
|
viewModel.setEditTodoItem(null)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package cn.super12138.todo.ui.pages.editor
|
package cn.super12138.todo.ui.pages.editor
|
||||||
|
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
|
@ -9,17 +11,26 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.sizeIn
|
||||||
|
import androidx.compose.foundation.layout.wrapContentWidth
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.ButtonColors
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Delete
|
||||||
|
import androidx.compose.material.icons.outlined.Save
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FilledTonalButton
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.Label
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.PlainTooltip
|
||||||
|
import androidx.compose.material3.Slider
|
||||||
|
import androidx.compose.material3.SliderDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableFloatStateOf
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
|
@ -28,13 +39,17 @@ import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
|
import androidx.compose.ui.semantics.semantics
|
||||||
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.logic.database.TodoEntity
|
import cn.super12138.todo.logic.database.TodoEntity
|
||||||
import cn.super12138.todo.logic.model.Subjects
|
import cn.super12138.todo.logic.model.Subjects
|
||||||
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.FilterChipGroup
|
import cn.super12138.todo.ui.components.FilterChipGroup
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
||||||
|
import cn.super12138.todo.ui.pages.main.components.getPriorityString
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -45,11 +60,65 @@ fun TodoEditorPage(
|
||||||
onNavigateUp: () -> Unit,
|
onNavigateUp: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
|
BackHandler {
|
||||||
|
onNavigateUp()
|
||||||
|
}
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||||
|
|
||||||
|
var text by rememberSaveable { mutableStateOf(toDo?.content ?: "") }
|
||||||
|
var isError by rememberSaveable { mutableStateOf(false) }
|
||||||
|
var selectedItemIndex by rememberSaveable { mutableIntStateOf(toDo?.subject ?: 0) }
|
||||||
|
var sliderPosition by rememberSaveable { mutableFloatStateOf(toDo?.priority ?: 0f) }
|
||||||
|
|
||||||
LargeTopAppBarScaffold(
|
LargeTopAppBarScaffold(
|
||||||
title = stringResource(if (toDo != null) R.string.title_edit_task else R.string.action_add_task),
|
title = stringResource(if (toDo != null) R.string.title_edit_task else R.string.action_add_task),
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
|
floatingActionButton = {
|
||||||
|
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||||
|
if (toDo !== null) {
|
||||||
|
AnimatedExtendedFloatingActionButton(
|
||||||
|
icon = {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.Delete,
|
||||||
|
contentDescription = stringResource(R.string.action_delete)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
text = { Text(stringResource(R.string.action_delete)) },
|
||||||
|
expanded = true,
|
||||||
|
containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||||
|
onClick = onDelete
|
||||||
|
)
|
||||||
|
}
|
||||||
|
AnimatedExtendedFloatingActionButton(
|
||||||
|
icon = {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.Save,
|
||||||
|
contentDescription = stringResource(R.string.action_save)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
text = { Text(stringResource(R.string.action_save)) },
|
||||||
|
expanded = true,
|
||||||
|
onClick = {
|
||||||
|
if (text.trim().isEmpty()) {
|
||||||
|
isError = true
|
||||||
|
return@AnimatedExtendedFloatingActionButton
|
||||||
|
}
|
||||||
|
|
||||||
|
isError = false
|
||||||
|
onSave(
|
||||||
|
TodoEntity(
|
||||||
|
content = text,
|
||||||
|
subject = selectedItemIndex,
|
||||||
|
isCompleted = toDo?.isCompleted ?: false,
|
||||||
|
priority = sliderPosition,
|
||||||
|
id = toDo?.id ?: 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
onBack = onNavigateUp,
|
onBack = onNavigateUp,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
|
|
@ -60,8 +129,6 @@ fun TodoEditorPage(
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
var text by rememberSaveable { mutableStateOf(toDo?.content ?: "") }
|
|
||||||
var isError by rememberSaveable { mutableStateOf(false) }
|
|
||||||
TextField(
|
TextField(
|
||||||
value = text,
|
value = text,
|
||||||
onValueChange = { text = it },
|
onValueChange = { text = it },
|
||||||
|
|
@ -82,11 +149,13 @@ fun TodoEditorPage(
|
||||||
it.getDisplayName(context)
|
it.getDisplayName(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var selectedItemIndex by rememberSaveable { mutableIntStateOf(toDo?.subject ?: 0) }
|
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.label_subject),
|
text = stringResource(R.string.label_subject),
|
||||||
style = MaterialTheme.typography.titleMedium
|
style = MaterialTheme.typography.titleMedium
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Spacer(Modifier.size(5.dp))
|
||||||
|
|
||||||
FilterChipGroup(
|
FilterChipGroup(
|
||||||
items = subjects,
|
items = subjects,
|
||||||
defaultSelectedItemIndex = toDo?.subject ?: 0,
|
defaultSelectedItemIndex = toDo?.subject ?: 0,
|
||||||
|
|
@ -96,47 +165,45 @@ fun TodoEditorPage(
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.size(20.dp))
|
Spacer(Modifier.size(10.dp))
|
||||||
|
|
||||||
// 操作按钮
|
Text(
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
|
text = stringResource(R.string.label_priority),
|
||||||
if (toDo !== null) {
|
style = MaterialTheme.typography.titleMedium
|
||||||
FilledTonalButton(
|
)
|
||||||
onClick = {
|
|
||||||
onDelete()
|
Spacer(Modifier.size(5.dp))
|
||||||
|
|
||||||
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
|
|
||||||
|
Slider(
|
||||||
|
modifier = Modifier.semantics {
|
||||||
|
contentDescription = context.getString(R.string.label_priority)
|
||||||
|
},
|
||||||
|
value = sliderPosition,
|
||||||
|
onValueChange = { sliderPosition = it },
|
||||||
|
valueRange = -10f..10f,
|
||||||
|
steps = 3,
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
thumb = {
|
||||||
|
Label(
|
||||||
|
label = {
|
||||||
|
PlainTooltip(
|
||||||
|
modifier = Modifier
|
||||||
|
.sizeIn(45.dp, 25.dp)
|
||||||
|
.wrapContentWidth()
|
||||||
|
) {
|
||||||
|
Text(stringResource(getPriorityString(sliderPosition)))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
colors = ButtonColors(
|
interactionSource = interactionSource
|
||||||
containerColor = MaterialTheme.colorScheme.errorContainer,
|
|
||||||
contentColor = MaterialTheme.colorScheme.onErrorContainer,
|
|
||||||
disabledContainerColor = MaterialTheme.colorScheme.onSurface,
|
|
||||||
disabledContentColor = MaterialTheme.colorScheme.onSurfaceVariant
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.action_delete))
|
SliderDefaults.Thumb(interactionSource)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FilledTonalButton(
|
)
|
||||||
onClick = {
|
|
||||||
// 文本为空
|
|
||||||
if (text.trim().isEmpty()) {
|
|
||||||
isError = true
|
|
||||||
return@FilledTonalButton
|
|
||||||
}
|
|
||||||
|
|
||||||
isError = false
|
Spacer(Modifier.size(40.dp))
|
||||||
onSave(
|
|
||||||
TodoEntity(
|
|
||||||
content = text,
|
|
||||||
subject = selectedItemIndex,
|
|
||||||
isCompleted = toDo?.isCompleted ?: false,
|
|
||||||
id = toDo?.id ?: 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Text(stringResource(R.string.action_save))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,6 +125,7 @@ fun MainPage(
|
||||||
content = content,
|
content = content,
|
||||||
subject = subject,
|
subject = subject,
|
||||||
isCompleted = true,
|
isCompleted = true,
|
||||||
|
priority = priority,
|
||||||
id = id
|
id = id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -166,6 +167,7 @@ fun MainPage(
|
||||||
content = content,
|
content = content,
|
||||||
subject = subject,
|
subject = subject,
|
||||||
isCompleted = true,
|
isCompleted = true,
|
||||||
|
priority = priority,
|
||||||
id = id
|
id = id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,11 @@ fun ManagerFragment(
|
||||||
content = item.content,
|
content = item.content,
|
||||||
subject = Subjects.fromId(item.subject).getDisplayName(context),
|
subject = Subjects.fromId(item.subject).getDisplayName(context),
|
||||||
completed = item.isCompleted,
|
completed = item.isCompleted,
|
||||||
|
priority = item.priority,
|
||||||
|
selected = selectedTodoIds.contains(item.id),
|
||||||
onCardClick = { onItemClick(item) },
|
onCardClick = { onItemClick(item) },
|
||||||
onCardLongClick = { onItemLongClick(item) },
|
onCardLongClick = { onItemLongClick(item) },
|
||||||
onChecked = { onItemChecked(item) },
|
onChecked = { onItemChecked(item) },
|
||||||
selected = selectedTodoIds.contains(item.id),
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(vertical = 5.dp)
|
.padding(vertical = 5.dp)
|
||||||
.animateItem() // TODO: 设置动画时间
|
.animateItem() // TODO: 设置动画时间
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,10 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextDecoration
|
import androidx.compose.ui.text.style.TextDecoration
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
|
|
||||||
|
|
@ -37,10 +39,11 @@ fun TodoCard(
|
||||||
content: String,
|
content: String,
|
||||||
subject: String,
|
subject: String,
|
||||||
completed: Boolean,
|
completed: Boolean,
|
||||||
|
priority: Float,
|
||||||
|
selected: Boolean,
|
||||||
onCardClick: () -> Unit = {},
|
onCardClick: () -> Unit = {},
|
||||||
onCardLongClick: () -> Unit = {},
|
onCardLongClick: () -> Unit = {},
|
||||||
onChecked: () -> Unit = {},
|
onChecked: () -> Unit = {},
|
||||||
selected: Boolean,
|
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
ElevatedCard(
|
ElevatedCard(
|
||||||
|
|
@ -85,14 +88,27 @@ fun TodoCard(
|
||||||
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.basicMarquee() // TODO: 后续评估性能影响
|
modifier = Modifier
|
||||||
)
|
.fillMaxWidth()
|
||||||
Text(
|
.basicMarquee() // TODO: 后续评估性能影响
|
||||||
text = subject,
|
|
||||||
style = MaterialTheme.typography.labelMedium,
|
|
||||||
textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None,
|
|
||||||
maxLines = 1
|
|
||||||
)
|
)
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = subject,
|
||||||
|
style = MaterialTheme.typography.labelMedium,
|
||||||
|
textDecoration = if (completed) TextDecoration.LineThrough else TextDecoration.None,
|
||||||
|
maxLines = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
PriorityText(
|
||||||
|
priority = priority,
|
||||||
|
isCompleted = completed
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimatedVisibility(!selected && !completed) {
|
AnimatedVisibility(!selected && !completed) {
|
||||||
|
|
@ -123,4 +139,54 @@ fun TodoCard(
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PriorityText(
|
||||||
|
priority: Float,
|
||||||
|
isCompleted: Boolean,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(getPriorityString(priority)),
|
||||||
|
style = MaterialTheme.typography.labelMedium.copy(
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = when (priority) {
|
||||||
|
-10f -> MaterialTheme.colorScheme.outline
|
||||||
|
-5f -> MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
0f -> MaterialTheme.colorScheme.secondary
|
||||||
|
5f -> MaterialTheme.colorScheme.tertiary
|
||||||
|
10f -> MaterialTheme.colorScheme.onErrorContainer
|
||||||
|
else -> MaterialTheme.colorScheme.secondary
|
||||||
|
}
|
||||||
|
),
|
||||||
|
textDecoration = if (isCompleted) TextDecoration.LineThrough else TextDecoration.None,
|
||||||
|
maxLines = 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPriorityString(priority: Float): Int {
|
||||||
|
return when (priority) {
|
||||||
|
-10f -> R.string.priority_not_urgent
|
||||||
|
-5f -> R.string.priority_not_important
|
||||||
|
0f -> R.string.priority_default
|
||||||
|
5f -> R.string.priority_important
|
||||||
|
10f -> R.string.priority_urgent
|
||||||
|
else -> R.string.priority_default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(locale = "zh-rCN", showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun TodoCardPreview() {
|
||||||
|
TodoCard(
|
||||||
|
content = "背《岳阳楼记》《出师表》《琵琶行》",
|
||||||
|
subject = "语文",
|
||||||
|
completed = false,
|
||||||
|
priority = 5f,
|
||||||
|
selected = false,
|
||||||
|
onCardClick = {},
|
||||||
|
onCardLongClick = {},
|
||||||
|
onChecked = {}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -40,4 +40,10 @@
|
||||||
<string name="pref_licence">开放源代码许可</string>
|
<string name="pref_licence">开放源代码许可</string>
|
||||||
<string name="pref_licence_desc">查看应用使用的开源库及其许可</string>
|
<string name="pref_licence_desc">查看应用使用的开源库及其许可</string>
|
||||||
<string name="label_subject">学科</string>
|
<string name="label_subject">学科</string>
|
||||||
|
<string name="priority_not_urgent">不紧急</string>
|
||||||
|
<string name="priority_not_important">不重要</string>
|
||||||
|
<string name="priority_default">默认</string>
|
||||||
|
<string name="priority_important">重要</string>
|
||||||
|
<string name="priority_urgent">紧急</string>
|
||||||
|
<string name="label_priority">优先级</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -41,4 +41,10 @@
|
||||||
<string name="pref_licence">Open Source Licences</string>
|
<string name="pref_licence">Open Source Licences</string>
|
||||||
<string name="pref_licence_desc">Check the open source libraries used by the application and their licences.</string>
|
<string name="pref_licence_desc">Check the open source libraries used by the application and their licences.</string>
|
||||||
<string name="label_subject">Subject</string>
|
<string name="label_subject">Subject</string>
|
||||||
|
<string name="priority_not_urgent">Not Urgent</string>
|
||||||
|
<string name="priority_not_important">Not Important</string>
|
||||||
|
<string name="priority_default">Default</string>
|
||||||
|
<string name="priority_important">Important</string>
|
||||||
|
<string name="priority_urgent">Urgent</string>
|
||||||
|
<string name="label_priority">Priority</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in a new issue