feat: 将待办 BottomSheet 提取为单独页面
This commit is contained in:
parent
9f3fd5f7ec
commit
ca08c21ca5
6 changed files with 48 additions and 66 deletions
|
|
@ -6,6 +6,7 @@ import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
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.main.MainPage
|
||||||
import cn.super12138.todo.ui.pages.settings.SettingsAbout
|
import cn.super12138.todo.ui.pages.settings.SettingsAbout
|
||||||
import cn.super12138.todo.ui.pages.settings.SettingsAboutLicence
|
import cn.super12138.todo.ui.pages.settings.SettingsAboutLicence
|
||||||
|
|
@ -51,10 +52,32 @@ fun TodoNavigation(
|
||||||
composable(TodoScreen.Main.name) {
|
composable(TodoScreen.Main.name) {
|
||||||
MainPage(
|
MainPage(
|
||||||
viewModel = viewModel,
|
viewModel = viewModel,
|
||||||
|
toTodoEditPage = { navController.navigate(TodoScreen.TodoEditor.name) },
|
||||||
toSettingsPage = { navController.navigate(TodoScreen.SettingsMain.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) {
|
composable(TodoScreen.SettingsMain.name) {
|
||||||
SettingsMain(
|
SettingsMain(
|
||||||
onNavigateUp = { navController.navigateUp() },
|
onNavigateUp = { navController.navigateUp() },
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package cn.super12138.todo.ui.navigation
|
||||||
|
|
||||||
enum class TodoScreen {
|
enum class TodoScreen {
|
||||||
Main,
|
Main,
|
||||||
|
TodoEditor,
|
||||||
SettingsMain,
|
SettingsMain,
|
||||||
SettingsAbout,
|
SettingsAbout,
|
||||||
SettingsAboutLicence
|
SettingsAboutLicence
|
||||||
|
|
|
||||||
|
|
@ -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.animation.AnimatedVisibility
|
||||||
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
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
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
|
||||||
|
|
@ -14,11 +15,9 @@ import androidx.compose.material3.ButtonColors
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FilledTonalButton
|
import androidx.compose.material3.FilledTonalButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
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.Text
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
|
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.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
|
@ -26,7 +25,6 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
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.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
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.logic.model.Subjects
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
import cn.super12138.todo.ui.components.FilterChipGroup
|
import cn.super12138.todo.ui.components.FilterChipGroup
|
||||||
|
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun TodoBottomSheet(
|
fun TodoEditorPage(
|
||||||
sheetState: SheetState,
|
|
||||||
onDismissRequest: () -> Unit,
|
|
||||||
toDo: TodoEntity? = null,
|
toDo: TodoEntity? = null,
|
||||||
onSave: (TodoEntity) -> Unit,
|
onSave: (TodoEntity) -> Unit,
|
||||||
onClose: () -> Unit,
|
|
||||||
onDelete: () -> Unit,
|
onDelete: () -> Unit,
|
||||||
|
onNavigateUp: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||||
ModalBottomSheet(
|
LargeTopAppBarScaffold(
|
||||||
sheetState = sheetState,
|
title = stringResource(if (toDo != null) R.string.title_edit_task else R.string.action_add_task),
|
||||||
onDismissRequest = onDismissRequest,
|
scrollBehavior = scrollBehavior,
|
||||||
|
onBack = onNavigateUp,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
) { innerPadding ->
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.padding(innerPadding)
|
||||||
.padding(horizontal = TodoDefaults.screenPadding)
|
.padding(horizontal = TodoDefaults.screenPadding)
|
||||||
|
.fillMaxSize()
|
||||||
.verticalScroll(rememberScrollState())
|
.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 text by rememberSaveable { mutableStateOf(toDo?.content ?: "") }
|
||||||
var isError by rememberSaveable { mutableStateOf(false) }
|
var isError by rememberSaveable { mutableStateOf(false) }
|
||||||
TextField(
|
TextField(
|
||||||
|
|
@ -91,6 +83,10 @@ fun TodoBottomSheet(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var selectedItemIndex by rememberSaveable { mutableIntStateOf(toDo?.subject ?: 0) }
|
var selectedItemIndex by rememberSaveable { mutableIntStateOf(toDo?.subject ?: 0) }
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.label_subject),
|
||||||
|
style = MaterialTheme.typography.titleMedium
|
||||||
|
)
|
||||||
FilterChipGroup(
|
FilterChipGroup(
|
||||||
items = subjects,
|
items = subjects,
|
||||||
defaultSelectedItemIndex = toDo?.subject ?: 0,
|
defaultSelectedItemIndex = toDo?.subject ?: 0,
|
||||||
|
|
@ -102,15 +98,12 @@ fun TodoBottomSheet(
|
||||||
|
|
||||||
Spacer(Modifier.size(20.dp))
|
Spacer(Modifier.size(20.dp))
|
||||||
|
|
||||||
|
// 操作按钮
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
|
Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||||
OutlinedButton(onClick = onClose) {
|
|
||||||
Text(stringResource(R.string.action_cancel))
|
|
||||||
}
|
|
||||||
if (toDo !== null) {
|
if (toDo !== null) {
|
||||||
FilledTonalButton(
|
FilledTonalButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
onDelete()
|
onDelete()
|
||||||
onClose()
|
|
||||||
},
|
},
|
||||||
colors = ButtonColors(
|
colors = ButtonColors(
|
||||||
containerColor = MaterialTheme.colorScheme.errorContainer,
|
containerColor = MaterialTheme.colorScheme.errorContainer,
|
||||||
|
|
@ -139,13 +132,11 @@ fun TodoBottomSheet(
|
||||||
id = toDo?.id ?: 0
|
id = toDo?.id ?: 0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
onClose()
|
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Text(stringResource(R.string.action_save))
|
Text(stringResource(R.string.action_save))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Spacer(Modifier.size(30.dp))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15,17 +15,14 @@ import androidx.compose.foundation.layout.ime
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.safeContent
|
import androidx.compose.foundation.layout.safeContent
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
|
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
|
||||||
import androidx.compose.material3.rememberModalBottomSheetState
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
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.Modifier
|
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.TodoFAB
|
||||||
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
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MainPage(
|
fun MainPage(
|
||||||
viewModel: MainViewModel,
|
viewModel: MainViewModel,
|
||||||
|
toTodoEditPage: () -> Unit,
|
||||||
toSettingsPage: () -> Unit,
|
toSettingsPage: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
|
|
@ -52,12 +48,8 @@ fun MainPage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val selectedEditTodoItem = viewModel.selectedEditTodo
|
|
||||||
val selectedTodoIds = viewModel.selectedTodoIds.collectAsState()
|
val selectedTodoIds = viewModel.selectedTodoIds.collectAsState()
|
||||||
var showBottomSheet by rememberSaveable { mutableStateOf(false) }
|
|
||||||
var showDeleteConfirmDialog by rememberSaveable { mutableStateOf(false) }
|
var showDeleteConfirmDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
|
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
|
||||||
|
|
||||||
|
|
@ -95,7 +87,7 @@ fun MainPage(
|
||||||
) {
|
) {
|
||||||
TodoFAB(
|
TodoFAB(
|
||||||
expanded = isExpanded,
|
expanded = isExpanded,
|
||||||
onClick = { showBottomSheet = true }
|
onClick = toTodoEditPage
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -117,8 +109,8 @@ fun MainPage(
|
||||||
list = filteredTodoList,
|
list = filteredTodoList,
|
||||||
onItemClick = { item ->
|
onItemClick = { item ->
|
||||||
if (isSelectedIdsEmpty) {
|
if (isSelectedIdsEmpty) {
|
||||||
showBottomSheet = true
|
|
||||||
viewModel.setEditTodoItem(item)
|
viewModel.setEditTodoItem(item)
|
||||||
|
toTodoEditPage()
|
||||||
} else {
|
} else {
|
||||||
viewModel.toggleTodoSelection(item)
|
viewModel.toggleTodoSelection(item)
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +151,6 @@ fun MainPage(
|
||||||
list = filteredTodoList,
|
list = filteredTodoList,
|
||||||
onItemClick = { item ->
|
onItemClick = { item ->
|
||||||
if (isSelectedIdsEmpty) {
|
if (isSelectedIdsEmpty) {
|
||||||
showBottomSheet = true
|
|
||||||
viewModel.setEditTodoItem(item)
|
viewModel.setEditTodoItem(item)
|
||||||
} else {
|
} else {
|
||||||
viewModel.toggleTodoSelection(item)
|
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) {
|
if (showDeleteConfirmDialog) {
|
||||||
TodoDeleteConfirmDialog(
|
TodoDeleteConfirmDialog(
|
||||||
onConfirm = {
|
onConfirm = {
|
||||||
|
|
|
||||||
|
|
@ -39,4 +39,5 @@
|
||||||
<string name="pref_developer">开发者</string>
|
<string name="pref_developer">开发者</string>
|
||||||
<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>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -40,4 +40,5 @@
|
||||||
<string name="pref_developer">Developer</string>
|
<string name="pref_developer">Developer</string>
|
||||||
<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>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in a new issue