乐于分享
好东西不私藏

安卓待办清单APP完整源代码

安卓待办清单APP完整源代码

部分源代码来自于AI,经调试修改校对后,最终之源代码。该源代码可以拷贝运行调试study,请勿用于商业用途。
package com.example.bringlistimport android.content.Contextimport androidx.compose.foundation.Image;import android.os.Bundleimport android.widget.Toastimport androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport androidx.compose.foundation.ExperimentalFoundationApiimport androidx.compose.foundation.backgroundimport androidx.compose.foundation.layout.*import androidx.compose.foundation.lazy.LazyColumnimport androidx.compose.foundation.lazy.itemsimport androidx.compose.foundation.shape.RoundedCornerShapeimport androidx.compose.material.icons.Iconsimport androidx.compose.material.icons.filled.Deleteimport androidx.compose.material.icons.filled.Doneimport androidx.compose.material.icons.filled.Infoimport androidx.compose.material.icons.filled.Personimport androidx.compose.material3.*import androidx.compose.runtime.*import androidx.compose.ui.Alignmentimport androidx.compose.ui.Modifierimport androidx.compose.ui.graphics.Colorimport androidx.compose.ui.platform.LocalContextimport androidx.compose.ui.res.painterResourceimport androidx.compose.ui.text.style.TextDecorationimport androidx.compose.ui.unit.dpimport androidx.lifecycle.lifecycleScopeimport java.util.Collections.listimport androidx.room.*import com.example.bringlist.ui.theme.BringlistThemeimport kotlinx.coroutines.Dispatchersimport kotlinx.coroutines.launchimport kotlinx.coroutines.withContextimport android.content.ClipDataimport android.content.ClipboardManagerimport androidx.compose.foundation.combinedClickableimport java.text.SimpleDateFormat;import java.util.Date;import java.util.Locale;// ====================== 1. 数据库实体(本地存储用)======================@Entity(tableName = "todo_table")data class Todo1(    @PrimaryKey val id: Int ,    val text: String,    val isDone: Boolean = false)// ====================== 2. Dao(增删改查)======================@Daointerface TodoDao {    @Query("SELECT * FROM todo_table")    funloadAllUsers():List<Todo1>    @Query("delete FROM todo_table")    suspend fundeleteAllUsers()    @Insert    suspend funinsert(todo: Todo1)    @Query("update todo_table set text=:newtext where text=:oldtext")    suspend funupdatetext(newtext:String,oldtext:String)    @Query("delete from todo_table where text=:texttemp")    suspend fundeletetodobytext(texttemp: String)    @Query("update todo_table set id=:newid where id=:tempid")    suspend funupdateid(newid:Int,tempid:Int)    @Query("update todo_table set isDone=:newisDone where text=:temptext")    suspend funupdatedata(newisDone: Boolean,temptext: String)}// ====================== 3. 数据库 ======================@Database(entities = [Todo1::class], version = 1, exportSchema = false)abstract class TodoDatabase : RoomDatabase() {    abstract funtodoDao(): TodoDao    companion object {        @Volatile        private var INSTANCE: TodoDatabase? = null        fungetInstance(context: android.content.Context): TodoDatabase {            return INSTANCE ?: synchronized(this) {                val instance = Room.databaseBuilder(                    context.applicationContext,                    TodoDatabase::class.java,                    "todo_database"                ).build()                INSTANCE = instance                instance            }        }    }}// 工具函数:显示Toast提示funshowToast(context: Context, message: String) {    Toast.makeText(context, message, Toast.LENGTH_LONG).show()}// 数据类:每个待办事项data class Todo(    var id: Int,    val text: String,    val isDone: Boolean = false)class MainActivity : ComponentActivity() {    private val todoList = mutableStateListOf<Todo>()    private lateinit var todoDao:TodoDao    // 定义一个变量存储获取todoList的回调函数    // private var getTodoListCallback: (() -> List<Todo>)? = null    override funonCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        init()        setContent {            // 主题            BringlistTheme {                Surface(                    modifier = Modifier.fillMaxSize(),                    color = MaterialTheme.colorScheme.background                ) {                    TodoApp(   todoList = todoList          //              initialTodos = initialTodos,                    ) // 主界面                }            }        }    }    funinit()    {        todoDao=TodoDatabase.getInstance(this).todoDao()         lifecycleScope.launch(Dispatchers.IO) {            val savedTodos=todoDao.loadAllUsers()            withContext(Dispatchers.Main){                todoList.clear()                todoList.addAll(                       savedTodos.map {todo1 ->                        Todo(                            id=todo1.id,                            text=todo1.text,                            isDone = todo1.isDone                        )                    }                )            }        }    }     override funonResume() {        super.onResume()        init()    }}// 主界面@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)@ComposablefunTodoApp(  todoList:MutableList<Todo>//  initialTodos: List<Todo>,  ) {    // 获取上下文(用于Toast提示)    val context = LocalContext.current    val todoDao = TodoDatabase.getInstance(context).todoDao()    // 输入框内容    var newTodoText by remember { mutableStateOf("") }    // ========== 对话框相关状态 ==========    var showUnCarriedDialog by remember { mutableStateOf(false) } // 未携带对话框显示状态    var showCarriedDialog by remember { mutableStateOf(false) }   // 已携带对话框显示状态    var showPersonInfoDialog by remember { mutableStateOf(false) } // 个人信息对话框    // 存储要显示的提示内容    var dialogTitle by remember { mutableStateOf("") }    var dialogContent by remember { mutableStateOf("") }    // 编辑相关状态    var showEditDialog by remember { mutableStateOf(false) }    var currentEditTodo by remember { mutableStateOf<Todo?>(null) }    var editText by remember { mutableStateOf("") }    val coroutineScope = rememberCoroutineScope()    // 构建未携带物件的提示内容    funbuildUnCarriedContent() {        val unCarriedItems = todoList.filter { !it.isDone }        dialogTitle = "未完成事项"//携带物品"        dialogContent = if (unCarriedItems.isEmpty()) {            "所有事项都完成"//物件都已携带"        } else {            unCarriedItems.joinToString(separator = "\n") { "• ${it.text}" }        }        showUnCarriedDialog = true    }    // 构建已携带物件的提示内容    funbuildCarriedContent() {        val carriedItems = todoList.filter { it.isDone }        dialogTitle = "已完成事项"//已携带物品"        dialogContent = if (carriedItems.isEmpty()) {            "暂无已完成事项"//携带物品"        } else {            carriedItems.joinToString(separator = "\n") { "• ${it.text}" }        }        showCarriedDialog = true    }    Box(        modifier = Modifier            .fillMaxSize()            .padding(16.dp)    ) {        Column(            modifier = Modifier                .fillMaxSize()                .padding(16.dp)        ) {            // 顶部:输入框 + 添加按钮            Row(                modifier = Modifier.fillMaxWidth(),                verticalAlignment = Alignment.CenterVertically            ) {                TextField(                    value = newTodoText,                    onValueChange = { newTodoText = it },                    modifier = Modifier.weight(1f),                    placeholder = { Text("请输入待办事项") },//需携带物品                    singleLine = true                )                Spacer(modifier = Modifier.width(5.dp))                Button(onClick = {                    if (newTodoText.isNotBlank()) {                        todoList.add(                            Todo(                                id =  todoList.size + 1,                                text = newTodoText                            )                        )                        newTodoText = "" // 清空输入框                        coroutineScope.launch {                            var i=todoList.size-1                            todoDao.insert (Todo1(todoList[i].id, todoList[i].text, todoList[i].isDone))                        }                    }                }                ) {                    Text("添加")                }                Spacer(modifier = Modifier.width(5.dp))                Button(onClick = {                    val clipboardManager =                        context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager                    // val Items=todoList.listIterator()                    val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())                    var text = sdf.format(Date())+"\n"                    //var text=""                    todoList.forEach { item ->                        text += if (item.isDone) item.text+"(已完成)\n" else item.text+"(未完成)\n"                    }                    //var text=todoList.joinToString(separator = "\n") { " ${it.text}" }                    val clipData = ClipData.newPlainText("text_label", text)                    clipboardManager.setPrimaryClip(clipData)                    showToast(context, "复制成功")                }                    //colors = ButtonDefaults.buttonColors(containerColor = Color.Blue, contentColor = Color.White)                ) {                    Text("导出")                }            }            Spacer(modifier = Modifier.height(16.dp))            // 列表            LazyColumn(                modifier = Modifier.fillMaxWidth()            ) {                items(todoList, key = { it.id }) { todo ->                    TodoItem(                        todo = todo,                        onToggle = { isDone ->                            todoList[todoList.indexOfFirst { it.id == todo.id }] = todo.copy(isDone = isDone)//状态传进去,并拷贝                            coroutineScope.launch {                                todoDao.updatedata(isDone,todo.text)                            }                        },                        onDelete = {                            todoList.remove(todo)                            for(i in todo.id..todoList.size){                                todoList[i-1].id=i                            }                            //写数据库更改id                            coroutineScope.launch {                                todoDao.deletetodobytext(todo.text)                                for(i in todo.id..todoList.size){                                    todoDao.updateid(i,i+1)                                }                            }                        },                        // 长按触发编辑                        onLongClick = {                            currentEditTodo = todo                            editText = todo.text                            showEditDialog = true                        }                    )                }            }        }        // ========== 底部悬浮按钮(重构为垂直布局) ==========        Column(            modifier = Modifier                .align(Alignment.BottomEnd)                .padding(bottom = 40.dp, end = 16.dp),            verticalArrangement = Arrangement.spacedBy(12.dp) // 按钮垂直间距        ) {            // 第三个悬浮按钮:个人信息(位于最上方)            FloatingActionButton(                onClick = { showPersonInfoDialog = true }, // 激活个人信息对话框                containerColor = MaterialTheme.colorScheme.primary, // 第三色,区分前两个按钮                modifier = Modifier                    .size(56.dp)                    .offset(x = 68.dp, y = 0.dp) // 向右偏移 8dp,贴近右边缘            ) {                Icon(Icons.Default.Person, contentDescription = "个人信息", tint = Color.White)            }            // ========== 关键修改2:底部悬浮按钮区域 ==========            Row(                horizontalArrangement = Arrangement.spacedBy(12.dp) // 水平间距            ) {                // 悬浮按钮1:提示所有未携带物件                FloatingActionButton(                    onClick = {                        buildUnCarriedContent()                    },                    containerColor = MaterialTheme.colorScheme.primary, // 红色强调未完成                    modifier = Modifier.size(56.dp)                ) {                    Icon(Icons.Default.Info, contentDescription = "未携带物品", tint = Color.White)                }                // 悬浮按钮2:提示所有已携带物件                FloatingActionButton(                    onClick = {                        buildCarriedContent()                    },                    containerColor = MaterialTheme.colorScheme.primary, // 主题主色                    modifier = Modifier.size(56.dp)                ) {                    Icon(Icons.Default.Done, contentDescription = "已携带物品", tint = Color.White)                }            }        }    }    // ========== 未携带物件对话框 ==========    if (showUnCarriedDialog) {        AlertDialog(            onDismissRequest = { showUnCarriedDialog = false }, // 点击外部关闭            title = { Text(dialogTitle) },            text = { Text(dialogContent) },            confirmButton = {                TextButton(onClick = { showUnCarriedDialog = false }) {                    Text("确认")                }            }        )    }    // ========== 已携带物件对话框 ==========    if (showCarriedDialog) {        AlertDialog(            onDismissRequest = { showCarriedDialog = false },            title = { Text(dialogTitle) },            text = { Text(dialogContent) },            confirmButton = {                TextButton(onClick = { showCarriedDialog = false }) {                    Text("确认")                }            }        )    }    // ========== 新增:个人信息对话框(含二维码) ==========    if (showPersonInfoDialog) {        AlertDialog(            onDismissRequest = { showPersonInfoDialog = false },            title = { Text("赞赏", style = MaterialTheme.typography.titleLarge) },            // 自定义对话框内容:二维码 + 个人信息            text = {                Column(                    horizontalAlignment = Alignment.CenterHorizontally,                    verticalArrangement = Arrangement.spacedBy(16.dp),                    modifier = Modifier.padding(8.dp)                ) {                    // 二维码图片(支持本地/网络图片)                    Image(                        painter = painterResource(id = R.drawable.shoukuanma), // qrcode 是你放在 drawable 里的二维码图片名                        contentDescription = "收款码",                        modifier = Modifier                            .size(250.dp)                            .background(Color.White, RoundedCornerShape(8.dp))                            .padding(8.dp),                        alignment = Alignment.Center                    )                    // 个人信息文本                    Column(                        horizontalAlignment = Alignment.CenterHorizontally,                        verticalArrangement = Arrangement.spacedBy(8.dp)                    ) {                        Text("可截图二维码...”", style = MaterialTheme.typography.bodyMedium)                        Text("识别二维码赞助...", style = MaterialTheme.typography.bodyMedium)                        Text("可关注公众号“路边米花”赞赏", style = MaterialTheme.typography.bodyMedium)//, color = Color.Gray)                    }                }            },            confirmButton = {                TextButton(onClick = { showPersonInfoDialog = false }) {                    Text("关闭")                }            },            // 调整对话框形状和内边距            shape = RoundedCornerShape(12.dp),            modifier = Modifier.padding(16.dp)        )    }//}// 编辑对话框    if (showEditDialog && currentEditTodo != null) {        val oldtext= currentEditTodo!!.text        AlertDialog(            onDismissRequest = { showEditDialog = false },            title = { Text("编辑待办") },            text = {                TextField(                    value = editText,                    onValueChange = { editText = it },                    singleLine = true,                    modifier = Modifier.fillMaxWidth()                )            },            confirmButton = {                Button(onClick = {                    currentEditTodo?.let { todo ->                        val index = todoList.indexOf(todo)                        if (index != -1 && editText.isNotBlank()) {                            todoList[index] = todo.copy(text = editText)                        }                    }                    showEditDialog = false                    currentEditTodo = null                    coroutineScope.launch {                        todoDao.updatetext(editText, oldtext)                    }                }) {                    Text("保存")                }            },            dismissButton = {                Button(onClick = {                    showEditDialog = false                    currentEditTodo = null                }) {                    Text("取消")                }            }        )    }}// 单个待办条目@OptIn(ExperimentalFoundationApi::class)@ComposablefunTodoItem(    todo: Todo,    onToggle: (Boolean) -> Unit,    onDelete: () -> Unit,    onLongClick: () -> Unit) {    Row(        modifier = Modifier            .fillMaxWidth()            .background(MaterialTheme.colorScheme.surface)            .combinedClickable(                onClick = {},                onLongClick = onLongClick // 长按            )            .padding(12.dp),        verticalAlignment = Alignment.CenterVertically    ) {        // 勾选框        Checkbox(            checked = todo.isDone,            onCheckedChange = onToggle        )        Text(            text = if(todo.isDone) todo.text+"(已完成)" else todo.text,            modifier = Modifier.weight(1f),            // 完成就加删除线            textDecoration = if (todo.isDone) TextDecoration.LineThrough else TextDecoration.None,            color = if (todo.isDone) Color.Gray else LocalContentColor.current        )        // 删除按钮        IconButton(onClick = onDelete) {            Icon(Icons.Default.Delete, contentDescription = "删除")        }    }}