复制代码
package com.example.myapplication
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 android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.util.Log
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.getValue
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.material3.Surface
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import com.example.myapplication.printDatabase
import com.example.myapplication.ui.theme.MyApplicationTheme
import kotlinx.coroutines.delay
import kotlin.collections.addAll
import kotlin.text.clear
// 数据类,表示数据库中的一个项目
data class Item(val id: Int? = null, val name: String, val description: String)
// 数据库帮助类,用于管理数据库的创建、升级和数据操作
class DatabaseHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
companion object {
private const val DATABASE_NAME = "item_database" // 数据库名称
private const val DATABASE_VERSION = 1 // 数据库版本
private const val TABLE_NAME = "items" // 表名
private const val COLUMN_ID = "id" // ID 列名
private const val COLUMN_NAME = "name" // 名称列名
private const val COLUMN_DESCRIPTION = "description" // 描述列名
}
// 创建数据库表
override fun onCreate(db: SQLiteDatabase) {
val createTableQuery = "CREATE TABLE $TABLE_NAME ($COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT, $COLUMN_NAME TEXT, $COLUMN_DESCRIPTION TEXT)"
db.execSQL(createTableQuery)
}
// 升级数据库表
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
val dropTableQuery = "DROP TABLE IF EXISTS $TABLE_NAME"
db.execSQL(dropTableQuery)
onCreate(db)
}
// 插入一个项目
fun insertItem(item: Item) {
val db = writableDatabase
val values = ContentValues().apply {
put(COLUMN_NAME, item.name)
put(COLUMN_DESCRIPTION, item.description)
}
db.insert(TABLE_NAME, null, values)
db.close()
}
// 获取所有项目
fun getAllItems(): List<Item> {
val db = readableDatabase
val query = "SELECT * FROM $TABLE_NAME"
val cursor = db.rawQuery(query, null)
val items = mutableListOf<Item>()
if (cursor.moveToFirst()) {
do {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_ID))
val name = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_NAME))
val description = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DESCRIPTION))
items.add(Item(id, name, description))
} while (cursor.moveToNext())
}
cursor.close()
db.close()
return items
}
// 删除一个项目
fun deleteItem(itemId: Int) {
val db = writableDatabase
db.delete(TABLE_NAME, "$COLUMN_ID=?", arrayOf(itemId.toString()))
db.close()
}
}
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
MyApplicationTheme {
/*
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
){
Surface(
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(vertical = 25.dp, horizontal = 8.dp)
) {
MainScreen()
}
}*/
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Surface(
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(innerPadding)
) {
MainScreen()
}
}
}
}
}
}
@Composable
fun MainScreen() {
val context = LocalContext.current
val dbHelper = remember { DatabaseHelper(context) } // 记住数据库帮助类实例
var itemName by remember { mutableStateOf("") } // 项目名称输入框的值
var itemDescription by remember { mutableStateOf("") } // 项目描述输入框的值
val items = remember { mutableStateListOf<Item>() } // 存储项目列表
val showDatabaseContent = remember { mutableStateOf(false) } // 是否显示数据库内容的标志
// 创建一个 MutableInteractionSource 来跟踪按钮的交互状态
val interactionSource = remember { MutableInteractionSource() }
// 获取按钮是否被按下的状态
val isPressed by interactionSource.collectIsPressedAsState()
// 根据按钮是否被按下,选择不同的颜色
val buttonColor = if (isPressed) {
Color(0xFF87CEEB) // 按下时的颜色 (更深的蓝色)
} else {
Color(0xFFADD8E6) // 默认颜色 (浅蓝色)
}
items.addAll(dbHelper.getAllItems()) // 初始化时从数据库加载数据
Column(modifier = Modifier.padding(1.dp)) {
// 项目名称输入框
OutlinedTextField(
value = itemName,
onValueChange = { itemName = it },
label = { Text("项目名称") },
modifier = Modifier
.fillMaxWidth()
.padding(1.dp),
colors = OutlinedTextFieldDefaults.colors(
focusedTextColor = Color.Black, // 获得焦点时的文本颜色
unfocusedTextColor = Color.Black, // 未获得焦点时的文本颜色
focusedLabelColor = Color.Blue, // 获得焦点时的标签颜色
unfocusedLabelColor = Color.Black, // 未获得焦点时的标签颜色
cursorColor = Color.Black, // 光标颜色
focusedBorderColor = Color.Blue, // 获得焦点时的边框颜色
unfocusedBorderColor = Color.Gray, // 未获得焦点时的边框颜色
//disabledBorderColor = Color.Gray, //禁用时的边框颜色
//errorBorderColor = Color.Red, // 错误时的边框颜色
)
)
// 项目描述输入框
OutlinedTextField(
value = itemDescription,
onValueChange = { itemDescription = it },
label = { Text("项目描述") },
modifier = Modifier
.fillMaxWidth()
.padding(1.dp),
colors = OutlinedTextFieldDefaults.colors(
focusedTextColor = Color.Black, // 获得焦点时的文本颜色
unfocusedTextColor = Color.Black, // 未获得焦点时的文本颜色
focusedLabelColor = Color.Blue, // 获得焦点时的标签颜色
unfocusedLabelColor = Color.Black, // 未获得焦点时的标签颜色
cursorColor = Color.Black, // 光标颜色
focusedBorderColor = Color.Blue, // 获得焦点时的边框颜色
unfocusedBorderColor = Color.Gray, // 未获得焦点时的边框颜色
//disabledBorderColor = Color.Gray, //禁用时的边框颜色
//errorBorderColor = Color.Red, // 错误时的边框颜色
)
)
// 添加项目按钮
/*
Button(
onClick = {
val newItem = Item(name = itemName, description = itemDescription)
dbHelper.insertItem(newItem) // 插入新项目到数据库
items.clear() // 清空列表
items.addAll(dbHelper.getAllItems()) // 重新从数据库加载数据
itemName = "" // 清空输入框
itemDescription = "" // 清空输入框
},
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFADD8E6)),
modifier = Modifier.fillMaxWidth()
) {
Text("添加项目")
}
*/
Button(
onClick = {
val newItem = Item(name = itemName, description = itemDescription)
dbHelper.insertItem(newItem) // 插入新项目到数据库
items.clear() // 清空列表
items.addAll(dbHelper.getAllItems()) // 重新从数据库加载数据
itemName = "" // 清空输入框
itemDescription = "" // 清空输入框
},
colors = ButtonDefaults.buttonColors(containerColor = buttonColor), // 使用动态的按钮颜色
modifier = Modifier.fillMaxWidth(),
interactionSource = interactionSource // 将 interactionSource 传递给 Button
) {
Text("添加项目")
}
// 显示/隐藏数据库按钮
Button(
onClick = {
showDatabaseContent.value = !showDatabaseContent.value // 切换显示/隐藏状态
},
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFADD8E6)),
) {
Text("显示/隐藏 数据库")
}
// 根据 showDatabaseContent 的值决定是否显示数据库内容
if (showDatabaseContent.value) {
DatabaseContentScreen(dbHelper) // 显示数据库内容
}
/*
LazyColumn(modifier = Modifier.padding(16.dp)) {
items(items) { item ->
ItemRow(item = item)
}
}*/
}
}
@Composable
fun ItemRow(item: Item) {
Column(modifier = Modifier.padding(8.dp)) {
Text(text = "Name: ${item.name}")
Text(text = "Description: ${item.description}")
}
}
// 数据库内容屏幕 Composable
@Composable
fun DatabaseContentScreen(dbHelper: DatabaseHelper) {
// 使用 remember 记住从数据库获取的数据,并转换为可变列表
val items = remember { dbHelper.getAllItems().toMutableList() }
// 记住当前选中的项目,初始为 null
var selectedItem by remember { mutableStateOf<Item?>(null) }
// 创建一个 LazyListState,用于控制 LazyColumn 的滚动
val lazyListState = rememberLazyListState()
Column(modifier = Modifier.padding(16.dp)) {
// 删除按钮
Button(
onClick = {
selectedItem?.let {
dbHelper.deleteItem(it.id!!) // 从数据库删除
items.remove(it) // 从列表中移除
selectedItem = null // 清空选中项
}
},
enabled = selectedItem != null, // 仅当有选中项时才启用
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFADD8E6)),
//modifier = Modifier.padding(top = 8.dp)
) {
Text("删除选中项")
}
// 表头
Row(modifier = Modifier
.fillMaxWidth()
.background(Color.LightGray)) {
TableCell(text = "ID", weight = 0.1f, isHeader = true) // ID 列
TableCell(text = "名称", weight = 0.4f, isHeader = true) // 名称列
TableCell(text = "描述", weight = 0.5f, isHeader = true) // 描述列
}
// 表格行
LazyColumn (
state = lazyListState, // 将 LazyListState 绑定到 LazyColumn
//reverseLayout = true // 设置反向布局,让列表从底部开始显示
){
items(items) { item ->
val isSelected = selectedItem?.id == item.id // 判断当前行是否被选中
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { selectedItem = if (isSelected) null else item } // 点击行时切换选中状态
.background(if (isSelected) Color.Cyan else Color.Transparent) // 根据选中状态改变背景色
) {
TableCell(text = item.id?.toString() ?: "", weight = 0.1f) // ID
TableCell(text = item.name, weight = 0.4f) // 名称
TableCell(text = item.description, weight = 0.5f) // 描述
}
}
}
// 使用 LaunchedEffect 在 items 改变时滚动到最底部
LaunchedEffect(items) {
if (items.isNotEmpty()) {
//lazyListState.scrollToItem(0) // 滚动到索引为 0 的项目,因为是反向布局,所以是最后一条数据
//lazyListState.scrollToItem(items.size - 1) // 滚动到最后一条数据
lazyListState.scrollToItem(items.lastIndex) // 滚动到最后一项
}
}
}
}
@Composable
fun TableCell(text: String, weight: Float, isHeader: Boolean = false) {
Text(
text = text,
modifier = Modifier
.padding(8.dp),
fontWeight = if (isHeader) FontWeight.Bold else FontWeight.Normal
)
}
fun printDatabase(dbHelper: DatabaseHelper) {
val items = dbHelper.getAllItems()
Log.d("DatabaseContent", "--- Database Content ---")
for (item in items) {
Log.d("DatabaseContent", "ID: ${item.id}, Name: ${item.name}, Description: ${item.description}")
}
Log.d("DatabaseContent", "--- End of Database Content ---")
}