feat: 将待办 BottomSheet 提取为单独页面

This commit is contained in:
Super12138 2025-01-16 22:09:46 +08:00
parent 9f3fd5f7ec
commit ca08c21ca5
6 changed files with 48 additions and 66 deletions

View file

@ -6,6 +6,7 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import cn.super12138.todo.ui.pages.editor.TodoEditorPage
import cn.super12138.todo.ui.pages.main.MainPage
import cn.super12138.todo.ui.pages.settings.SettingsAbout
import cn.super12138.todo.ui.pages.settings.SettingsAboutLicence
@ -51,10 +52,32 @@ fun TodoNavigation(
composable(TodoScreen.Main.name) {
MainPage(
viewModel = viewModel,
toTodoEditPage = { navController.navigate(TodoScreen.TodoEditor.name) },
toSettingsPage = { navController.navigate(TodoScreen.SettingsMain.name) }
)
}
composable(TodoScreen.TodoEditor.name) {
TodoEditorPage(
toDo = viewModel.selectedEditTodo,
onSave = {
viewModel.addTodo(it)
navController.navigateUp()
},
onDelete = {
if (viewModel.selectedEditTodo !== null) {
viewModel.deleteTodo(viewModel.selectedEditTodo!!)
viewModel.setEditTodoItem(null)
}
navController.navigateUp()
},
onNavigateUp = {
viewModel.setEditTodoItem(null)
navController.navigateUp()
}
)
}
composable(TodoScreen.SettingsMain.name) {
SettingsMain(
onNavigateUp = { navController.navigateUp() },

View file

@ -2,6 +2,7 @@ package cn.super12138.todo.ui.navigation
enum class TodoScreen {
Main,
TodoEditor,
SettingsMain,
SettingsAbout,
SettingsAboutLicence

View file

@ -1,10 +1,11 @@
package cn.super12138.todo.ui.pages.main
package cn.super12138.todo.ui.pages.editor
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@ -14,11 +15,9 @@ import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
@ -26,7 +25,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
@ -36,38 +34,32 @@ import cn.super12138.todo.logic.database.TodoEntity
import cn.super12138.todo.logic.model.Subjects
import cn.super12138.todo.ui.TodoDefaults
import cn.super12138.todo.ui.components.FilterChipGroup
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TodoBottomSheet(
sheetState: SheetState,
onDismissRequest: () -> Unit,
fun TodoEditorPage(
toDo: TodoEntity? = null,
onSave: (TodoEntity) -> Unit,
onClose: () -> Unit,
onDelete: () -> Unit,
onNavigateUp: () -> Unit,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
ModalBottomSheet(
sheetState = sheetState,
onDismissRequest = onDismissRequest,
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
LargeTopAppBarScaffold(
title = stringResource(if (toDo != null) R.string.title_edit_task else R.string.action_add_task),
scrollBehavior = scrollBehavior,
onBack = onNavigateUp,
modifier = modifier
) {
) { innerPadding ->
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(innerPadding)
.padding(horizontal = TodoDefaults.screenPadding)
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
Text(
text = stringResource(if (toDo != null) R.string.title_edit_task else R.string.action_add_task),
style = MaterialTheme.typography.headlineMedium
)
Spacer(Modifier.size(20.dp))
var text by rememberSaveable { mutableStateOf(toDo?.content ?: "") }
var isError by rememberSaveable { mutableStateOf(false) }
TextField(
@ -91,6 +83,10 @@ fun TodoBottomSheet(
}
}
var selectedItemIndex by rememberSaveable { mutableIntStateOf(toDo?.subject ?: 0) }
Text(
text = stringResource(R.string.label_subject),
style = MaterialTheme.typography.titleMedium
)
FilterChipGroup(
items = subjects,
defaultSelectedItemIndex = toDo?.subject ?: 0,
@ -102,15 +98,12 @@ fun TodoBottomSheet(
Spacer(Modifier.size(20.dp))
// 操作按钮
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
OutlinedButton(onClick = onClose) {
Text(stringResource(R.string.action_cancel))
}
if (toDo !== null) {
FilledTonalButton(
onClick = {
onDelete()
onClose()
},
colors = ButtonColors(
containerColor = MaterialTheme.colorScheme.errorContainer,
@ -139,13 +132,11 @@ fun TodoBottomSheet(
id = toDo?.id ?: 0
)
)
onClose()
}
) {
Text(stringResource(R.string.action_save))
}
}
Spacer(Modifier.size(30.dp))
}
}
}

View file

@ -15,17 +15,14 @@ import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeContent
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
@ -35,12 +32,11 @@ import cn.super12138.todo.ui.pages.main.components.TodoDeleteConfirmDialog
import cn.super12138.todo.ui.pages.main.components.TodoFAB
import cn.super12138.todo.ui.pages.main.components.TodoTopAppBar
import cn.super12138.todo.ui.viewmodels.MainViewModel
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainPage(
viewModel: MainViewModel,
toTodoEditPage: () -> Unit,
toSettingsPage: () -> Unit,
modifier: Modifier = Modifier
) {
@ -52,12 +48,8 @@ fun MainPage(
}
}
val selectedEditTodoItem = viewModel.selectedEditTodo
val selectedTodoIds = viewModel.selectedTodoIds.collectAsState()
var showBottomSheet by rememberSaveable { mutableStateOf(false) }
var showDeleteConfirmDialog by rememberSaveable { mutableStateOf(false) }
val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
val scope = rememberCoroutineScope()
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
@ -95,7 +87,7 @@ fun MainPage(
) {
TodoFAB(
expanded = isExpanded,
onClick = { showBottomSheet = true }
onClick = toTodoEditPage
)
}
},
@ -117,8 +109,8 @@ fun MainPage(
list = filteredTodoList,
onItemClick = { item ->
if (isSelectedIdsEmpty) {
showBottomSheet = true
viewModel.setEditTodoItem(item)
toTodoEditPage()
} else {
viewModel.toggleTodoSelection(item)
}
@ -159,7 +151,6 @@ fun MainPage(
list = filteredTodoList,
onItemClick = { item ->
if (isSelectedIdsEmpty) {
showBottomSheet = true
viewModel.setEditTodoItem(item)
} else {
viewModel.toggleTodoSelection(item)
@ -189,32 +180,6 @@ fun MainPage(
}
}
}
if (showBottomSheet) {
TodoBottomSheet(
sheetState = bottomSheetState,
onDismissRequest = {
showBottomSheet = false
viewModel.setEditTodoItem(null)
},
toDo = selectedEditTodoItem,
onSave = { toDo ->
viewModel.addTodo(toDo)
},
onClose = {
viewModel.setEditTodoItem(null)
scope
.launch { bottomSheetState.hide() }
.invokeOnCompletion {
if (!bottomSheetState.isVisible) {
showBottomSheet = false
}
}
},
onDelete = {
if (selectedEditTodoItem !== null) viewModel.deleteTodo(selectedEditTodoItem)
}
)
}
if (showDeleteConfirmDialog) {
TodoDeleteConfirmDialog(
onConfirm = {

View file

@ -39,4 +39,5 @@
<string name="pref_developer">开发者</string>
<string name="pref_licence">开放源代码许可</string>
<string name="pref_licence_desc">查看应用使用的开源库及其许可</string>
<string name="label_subject">学科</string>
</resources>

View file

@ -40,4 +40,5 @@
<string name="pref_developer">Developer</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="label_subject">Subject</string>
</resources>