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)
|
||||
}
|
||||
|
||||
ksp {
|
||||
arg("room.schemaLocation", "$projectDir/schemas")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "cn.super12138.todo"
|
||||
compileSdk = 35
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
<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>
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue