feat: 完成待办列表和数据库的绑定&更新数据库结构
This commit is contained in:
parent
daa9972651
commit
35c67e418a
16 changed files with 381 additions and 53 deletions
3
app/.gitignore
vendored
3
app/.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
/build
|
/build
|
||||||
|
/release
|
||||||
|
|
@ -6,6 +6,10 @@ plugins {
|
||||||
alias(libs.plugins.aboutlibraries)
|
alias(libs.plugins.aboutlibraries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ksp {
|
||||||
|
arg("room.schemaLocation", "$projectDir/schemas")
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "cn.super12138.todo"
|
namespace = "cn.super12138.todo"
|
||||||
compileSdk = 35
|
compileSdk = 35
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
android:theme="@style/Theme.ToDo"
|
android:theme="@style/Theme.ToDo"
|
||||||
tools:targetApi="35">
|
tools:targetApi="35">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".ui.activities.MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/Theme.ToDo">
|
android:theme="@style/Theme.ToDo">
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
package cn.super12138.todo
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.compose.setContent
|
|
||||||
import androidx.activity.enableEdgeToEdge
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import cn.super12138.todo.ui.theme.ToDoTheme
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
enableEdgeToEdge()
|
|
||||||
setContent {
|
|
||||||
ToDoTheme {
|
|
||||||
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
|
||||||
Greeting(
|
|
||||||
name = "Android",
|
|
||||||
modifier = Modifier.padding(innerPadding)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun Greeting(name: String, modifier: Modifier = Modifier) {
|
|
||||||
Text(
|
|
||||||
text = "Hello $name!",
|
|
||||||
modifier = modifier
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
@Composable
|
|
||||||
fun GreetingPreview() {
|
|
||||||
ToDoTheme {
|
|
||||||
Greeting("Android")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -6,9 +6,8 @@ import androidx.room.PrimaryKey
|
||||||
|
|
||||||
@Entity(tableName = "todo")
|
@Entity(tableName = "todo")
|
||||||
data class TodoEntity(
|
data class TodoEntity(
|
||||||
@ColumnInfo(name = "type") val type: Int,
|
|
||||||
@ColumnInfo(name = "content") val content: String,
|
@ColumnInfo(name = "content") val content: String,
|
||||||
@ColumnInfo(name = "subject") val subject: String,
|
@ColumnInfo(name = "subject") val subject: String,
|
||||||
@ColumnInfo(name = "completed") val isCompleted: Boolean = false,
|
@ColumnInfo(name = "completed") val isCompleted: Boolean = false,
|
||||||
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Long = 0L,
|
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Int = 0,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package cn.super12138.todo.ui.activities
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import cn.super12138.todo.ui.navigation.ToDoNavigation
|
||||||
|
import cn.super12138.todo.ui.theme.ToDoTheme
|
||||||
|
|
||||||
|
class MainActivity : ComponentActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
enableEdgeToEdge()
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContent {
|
||||||
|
ToDoTheme {
|
||||||
|
Surface(color = MaterialTheme.colorScheme.background) {
|
||||||
|
ToDoNavigation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package cn.super12138.todo.ui.navigation
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
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.main.MainPage
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ToDoNavigation(
|
||||||
|
navController: NavHostController = rememberNavController(),
|
||||||
|
startDestination: String = ToDoScreen.Main.name,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
NavHost(
|
||||||
|
navController = navController,
|
||||||
|
startDestination = startDestination,
|
||||||
|
modifier = modifier
|
||||||
|
) {
|
||||||
|
composable(ToDoScreen.Main.name) {
|
||||||
|
MainPage(
|
||||||
|
viewModel = viewModel()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package cn.super12138.todo.ui.navigation
|
||||||
|
|
||||||
|
enum class ToDoScreen {
|
||||||
|
Main,
|
||||||
|
Settings
|
||||||
|
}
|
||||||
112
app/src/main/kotlin/cn/super12138/todo/ui/pages/main/MainPage.kt
Normal file
112
app/src/main/kotlin/cn/super12138/todo/ui/pages/main/MainPage.kt
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
package cn.super12138.todo.ui.pages.main
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Add
|
||||||
|
import androidx.compose.material.icons.outlined.Settings
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.FloatingActionButton
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import cn.super12138.todo.R
|
||||||
|
import cn.super12138.todo.logic.database.TodoEntity
|
||||||
|
import cn.super12138.todo.ui.pages.main.components.TodoCard
|
||||||
|
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun MainPage(viewModel: MainViewModel, modifier: Modifier = Modifier) {
|
||||||
|
val toDoList = viewModel.toDos.collectAsState(initial = emptyList())
|
||||||
|
val listState = rememberLazyListState()
|
||||||
|
val isExpanded by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
listState.firstVisibleItemIndex == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(stringResource(R.string.app_name))
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
IconButton(
|
||||||
|
onClick = {}
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.Settings,
|
||||||
|
contentDescription = stringResource(R.string.pages_settings)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
floatingActionButton = {
|
||||||
|
FloatingActionButton(
|
||||||
|
onClick = {
|
||||||
|
viewModel.addTodo(
|
||||||
|
TodoEntity(
|
||||||
|
content = "测试内容",
|
||||||
|
subject = "测试学科"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.Add,
|
||||||
|
contentDescription = stringResource(R.string.action_add_todo)
|
||||||
|
)
|
||||||
|
AnimatedVisibility(isExpanded) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.action_add_todo),
|
||||||
|
modifier = Modifier.padding(start = 8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = modifier.fillMaxSize()
|
||||||
|
) { innerPadding ->
|
||||||
|
Column(modifier = Modifier.padding(innerPadding)) {
|
||||||
|
ProgressFragment(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(2f)
|
||||||
|
.fillMaxSize()
|
||||||
|
)
|
||||||
|
|
||||||
|
ManagerFragment(
|
||||||
|
state = listState,
|
||||||
|
list = toDoList.value,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(3f)
|
||||||
|
.fillMaxSize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package cn.super12138.todo.ui.pages.main
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import cn.super12138.todo.logic.database.TodoEntity
|
||||||
|
import cn.super12138.todo.ui.pages.main.components.TodoCard
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ManagerFragment(
|
||||||
|
state: LazyListState,
|
||||||
|
list: List<TodoEntity>,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = modifier,
|
||||||
|
state = state,
|
||||||
|
contentPadding = PaddingValues(
|
||||||
|
start = 10.dp,
|
||||||
|
end = 10.dp,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
items(
|
||||||
|
items = list,
|
||||||
|
key = { it.id }
|
||||||
|
) { item ->
|
||||||
|
TodoCard(
|
||||||
|
content = item.content,
|
||||||
|
subject = item.subject,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(vertical = 5.dp)
|
||||||
|
.animateItem()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
package cn.super12138.todo.ui.pages.main
|
||||||
|
|
||||||
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.ProgressIndicatorDefaults
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableFloatStateOf
|
||||||
|
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.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ProgressFragment(modifier: Modifier = Modifier) {
|
||||||
|
var progress by rememberSaveable { mutableFloatStateOf(0.1f) }
|
||||||
|
val animatedProgress by animateFloatAsState(
|
||||||
|
targetValue = progress,
|
||||||
|
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
|
||||||
|
label = "To Do Progress"
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = modifier,
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
progress = { animatedProgress },
|
||||||
|
strokeWidth = 10.dp,
|
||||||
|
gapSize = 10.dp,
|
||||||
|
modifier = Modifier.size(170.dp)
|
||||||
|
)
|
||||||
|
Column {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text(
|
||||||
|
text = "0",
|
||||||
|
style = MaterialTheme.typography.displaySmall.copy(
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "/",
|
||||||
|
style = MaterialTheme.typography.displayMedium.copy(
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "0",
|
||||||
|
style = MaterialTheme.typography.displayMedium.copy(
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*Slider(
|
||||||
|
value = progress,
|
||||||
|
onValueChange = { progress = it }
|
||||||
|
)*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package cn.super12138.todo.ui.pages.main.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Check
|
||||||
|
import androidx.compose.material3.ElevatedCard
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TodoCard(
|
||||||
|
content: String,
|
||||||
|
subject: String,
|
||||||
|
onCardClick: () -> Unit = {},
|
||||||
|
onChecked: () -> Unit = {},
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
ElevatedCard(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(80.dp),
|
||||||
|
onClick = onCardClick
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(start = 15.dp, end = 15.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = content,
|
||||||
|
style = MaterialTheme.typography.titleLarge
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = subject,
|
||||||
|
style = MaterialTheme.typography.labelLarge.copy(
|
||||||
|
fontSize = 11.sp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
IconButton(onClick = onChecked) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.Check,
|
||||||
|
tint = MaterialTheme.colorScheme.primary,
|
||||||
|
contentDescription = ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.super12138.todo.ui.viewmodels
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import cn.super12138.todo.logic.Repository
|
||||||
|
import cn.super12138.todo.logic.database.TodoEntity
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class MainViewModel : ViewModel() {
|
||||||
|
val toDos: Flow<List<TodoEntity>> = Repository.getAllTodos()
|
||||||
|
|
||||||
|
fun addTodo(toDo: TodoEntity) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
Repository.insertTodo(toDo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6
app/src/main/res/values-zh-rCN/strings.xml
Normal file
6
app/src/main/res/values-zh-rCN/strings.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">待办</string>
|
||||||
|
<string name="pages_settings">设置</string>
|
||||||
|
<string name="action_add_todo">添加待办</string>
|
||||||
|
</resources>
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">ToDo</string>
|
<string name="app_name">To Do</string>
|
||||||
|
<string name="pages_settings">Settings</string>
|
||||||
|
<string name="action_add_todo">Add todo</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -22,7 +22,7 @@ junit = "4.13.2"
|
||||||
junitVersion = "1.2.1"
|
junitVersion = "1.2.1"
|
||||||
espressoCore = "3.6.1"
|
espressoCore = "3.6.1"
|
||||||
# Plugins
|
# Plugins
|
||||||
agp = "8.7.3"
|
agp = "8.8.0"
|
||||||
kotlin = "2.1.0"
|
kotlin = "2.1.0"
|
||||||
ksp = "2.1.0-1.0.29"
|
ksp = "2.1.0-1.0.29"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue