feat: 完成待办列表和数据库的绑定&更新数据库结构

This commit is contained in:
Super12138 2025-01-11 18:23:05 +08:00
parent daa9972651
commit 35c67e418a
16 changed files with 381 additions and 53 deletions

3
app/.gitignore vendored
View file

@ -1 +1,2 @@
/build
/build
/release

View file

@ -6,6 +6,10 @@ plugins {
alias(libs.plugins.aboutlibraries)
}
ksp {
arg("room.schemaLocation", "$projectDir/schemas")
}
android {
namespace = "cn.super12138.todo"
compileSdk = 35

View file

@ -14,7 +14,7 @@
android:theme="@style/Theme.ToDo"
tools:targetApi="35">
<activity
android:name=".MainActivity"
android:name=".ui.activities.MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.ToDo">

View file

@ -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")
}
}

View file

@ -6,9 +6,8 @@ import androidx.room.PrimaryKey
@Entity(tableName = "todo")
data class TodoEntity(
@ColumnInfo(name = "type") val type: Int,
@ColumnInfo(name = "content") val content: String,
@ColumnInfo(name = "subject") val subject: String,
@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,
)

View file

@ -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()
}
}
}
}
}

View file

@ -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()
)
}
}
}

View file

@ -0,0 +1,6 @@
package cn.super12138.todo.ui.navigation
enum class ToDoScreen {
Main,
Settings
}

View 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()
)
}
}
}

View file

@ -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()
)
}
}
}

View file

@ -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 }
)*/
}
}

View file

@ -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 = ""
)
}
}
}
}

View file

@ -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)
}
}
}

View 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>

View file

@ -1,3 +1,5 @@
<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>

View file

@ -22,7 +22,7 @@ junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
# Plugins
agp = "8.7.3"
agp = "8.8.0"
kotlin = "2.1.0"
ksp = "2.1.0-1.0.29"