您的位置:首页 > 健康 > 养生 > 555建筑网挂靠官网_设计说明翻译_网站排名优化手机_太原seo霸屏

555建筑网挂靠官网_设计说明翻译_网站排名优化手机_太原seo霸屏

2025/4/22 0:32:24 来源:https://blog.csdn.net/wangz76/article/details/147354372  浏览:    关键词:555建筑网挂靠官网_设计说明翻译_网站排名优化手机_太原seo霸屏
555建筑网挂靠官网_设计说明翻译_网站排名优化手机_太原seo霸屏

package com.example.mynumsetimport android.app.Activity
import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.mynumset.ui.theme.MyNumSetTheme
import kotlinx.coroutines.launch
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.clickable
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.ui.window.Dialog
import java.time.Instant
import java.time.LocalDate
import java.time.LocalTime
import java.time.ZoneId
import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.compose.BackHandler
import androidx.compose.runtime.saveable.rememberSaveable
import kotlinx.coroutines.withContext
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.formatter.ValueFormatter
import androidx.compose.ui.viewinterop.AndroidView
import com.github.mikephil.charting.components.Legend
import com.github.mikephil.charting.components.LimitLine
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.res.painterResource// 在原有类中添加数据库帮助类(放在MainActivity类外)
class RecordDbHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION
) {init {// 添加连接池配置setWriteAheadLoggingEnabled(true)writableDatabase.enableWriteAheadLogging()}companion object {// 定义数据库的名称和版本private const val DATABASE_NAME = "health_records.db"private const val DATABASE_VERSION = 1}// 创建数据库表override fun onCreate(db: SQLiteDatabase) {// 执行SQL语句创建records表db.execSQL("""CREATE TABLE records (date TEXT NOT NULL,  time TEXT NOT NULL, low INTEGER NOT NULL, heart_rate INTEGER NOT NULL, status TEXT NOT NULL, PRIMARY KEY (date, time) )""")}// 升级数据库override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {// 如果存在records表,则删除db.execSQL("DROP TABLE IF EXISTS records")// 重新创建数据库表onCreate(db)}
}
// 定义一个数据类 HealthRecord,用于存储健康记录信息
data class HealthRecord(// 日期字段,存储记录的日期,类型为 Stringval date: String,// 时间字段,存储记录的时间,类型为 Stringval time: String,// 高血压字段,存储高压值,类型为 Intval high: Int,// 低压字段,存储低压值,类型为 Intval low: Int,// 心率字段,存储心率值,类型为 Intval heartRate: Int,// 状态字段,存储健康状态描述,类型为 Stringval status: String
)class MainActivity : ComponentActivity() {// 原色val originalGreen = Color(0xFFE8F5E9)// 加深方案(任选其一)val deepGreen1 = Color(0xFFC8E6C9)  // 浅灰绿(比原色深10%)val deepGreen2 = Color(0xFFA5D6A7)  // 中等青绿(Material Teal 200)val deepGreen3 = Color(0xFF80CBC4)  // 深青蓝色(Material Teal 300)val gradientColors = listOf(deepGreen2, deepGreen3)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()setContent {MyNumSetTheme {BottomNavigationExample()}}}
}@Composable
fun NumberPicker(modifier: Modifier = Modifier,initialValue: Int = 0,range: IntRange = 20..200,onValueChange: (Int) -> Unit
) {val itemHeight = 50.dpval startOffset = (initialValue - range.first).coerceIn(0 until range.count())//Log.d("initialValue=", "读取成功: $initialValue")val listState = rememberLazyListState(initialFirstVisibleItemIndex = startOffset)val coroutineScope = rememberCoroutineScope()val itemHeightPx = with(LocalDensity.current) { itemHeight.toPx() }// 实时计算当前选中项索引val selectedIndex by remember {derivedStateOf {val offset = listState.firstVisibleItemScrollOffsetval index = listState.firstVisibleItemIndexif (offset > itemHeightPx / 2) index + 1 else index}}// 当滚动停止时,吸附到中间项并回调LaunchedEffect(selectedIndex, listState.isScrollInProgress) {if (!listState.isScrollInProgress) {coroutineScope.launch {listState.animateScrollToItem(selectedIndex)}onValueChange((range.first + selectedIndex))}}LazyColumn(state = listState,modifier = modifier.height(itemHeight * 3).width(100.dp),horizontalAlignment = Alignment.CenterHorizontally,contentPadding = PaddingValues(vertical = itemHeight),flingBehavior = rememberSnapFlingBehavior(lazyListState = listState)) {items(range.count()) { index ->val value = range.first + indexval isSelected = selectedIndex == indexText(text = value.toString(),fontSize = if (isSelected) 32.sp else 20.sp,fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal,color = if (isSelected) Color.Black else Color.Gray,modifier = Modifier.height(itemHeight).fillMaxWidth(),textAlign = TextAlign.Center)}}
}// 定义 DataStore 的扩展属性,用于访问应用的设置数据存储
val Context.settingsDataStore: DataStore<Preferences> by preferencesDataStore(name = "my_settings")// PreferencesKeys 是一个单例对象,用于定义 DataStore 的键
private object PreferencesKeys {val NumbGy = intPreferencesKey("saved_gaoya")val NumbDy = intPreferencesKey("saved_diya")val NumbXl = intPreferencesKey("saved_xinlv")
}
@Composable
fun NumberPickerDemo(dbHelper: RecordDbHelper) {val context = LocalContext.currentval scope = rememberCoroutineScope() // 新增协程作用域//val dbHelper = remember { RecordDbHelper(context) }val coroutineScope = rememberCoroutineScope()var currentStatusText by remember { mutableStateOf("") }var currentStatusColor by remember { mutableStateOf(Color.Black) }var lastClickTime by remember { mutableStateOf(0L) }// 添加两个新状态var selectedNumberGy by remember { mutableStateOf<Int?>(null) }var selectedNumberDy by remember { mutableStateOf<Int?>(null) }var selectedNumberXl by remember { mutableStateOf<Int?>(null) }// 记住是否显示日期选择器的状态var showDatePicker by remember { mutableStateOf(false) }// 记住是否显示时间选择器的状态var showTimePicker by remember { mutableStateOf(false) }// 记住当前选中的日期和时间var selectedDateTime by remember { mutableStateOf(LocalDateTime.now()) }// 日期格式化器val dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.getDefault())// 时间格式化器val timeFormatter = DateTimeFormatter.ofPattern("HH:mm", Locale.getDefault())LaunchedEffect(Unit) {try {val preferences = context.settingsDataStore.data.first()selectedNumberGy = preferences[PreferencesKeys.NumbGy] ?: 100selectedNumberDy = preferences[PreferencesKeys.NumbDy] ?: 80selectedNumberXl = preferences[PreferencesKeys.NumbXl] ?: 75}catch (e: Exception) {Log.e("NumberPickerDemo", "读取设置失败", e)}}Column(modifier = Modifier.fillMaxSize(),verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally) {// 显示血压状态selectedNumberGy?.let { gy ->selectedNumberDy?.let { dy ->val (statusText, statusColor) = run {// 分别判断高压和低压的等级val gyLevel = when {gy < 90 -> 1gy in 90 until 120 -> 2gy in 120 until 140 -> 3gy in 140 until 160 -> 4gy in 160 until 180 -> 5gy >= 180 -> 6else -> 0}val dyLevel = when {dy < 60 -> 1dy in 60 until 80 -> 2dy in 80 until 90 -> 3dy in 90 until 100 -> 4dy in 100 until 110 -> 5dy >= 110 -> 6else -> 0}// 取最高等级作为最终结果when (maxOf(gyLevel, dyLevel)) {1 -> "低血压" to Color.Blue2 -> "正常血压" to Color(0xFF006400)3 -> "正常高值血压" to Color(0xFFFFB300)4 -> "1级高血压" to Color(0xFFFF6700)5 -> "2级高血压" to Color.Red6 -> "3级高血压" to Color.Redelse -> "****" to Color.Black}}.also {currentStatusText = it.firstcurrentStatusColor = it.second}Card(modifier = Modifier.padding(top = 50.dp, bottom = 50.dp).size(width = 350.dp, height = 140.dp).background(brush = Brush.verticalGradient(colors = listOf(Color.White.copy(alpha = 0.3f),Color.Transparent),startY = 0f,endY = 350f),shape = RoundedCornerShape(24.dp)),shape = RoundedCornerShape(24.dp),elevation = CardDefaults.cardElevation(4.dp)) {val density = LocalDensity.currentText(text = statusText,fontSize = 50.sp,color = statusColor,style = LocalTextStyle.current.copy(shadow = with(density) {Shadow(color = Color.Black.copy(alpha = 0.3f),offset = Offset(2.dp.toPx(), 2.dp.toPx()),blurRadius = 4f)}),fontWeight = FontWeight.Bold,modifier = Modifier.fillMaxSize().padding(24.dp),textAlign = TextAlign.Center)}}} ?: run {CircularProgressIndicator()}selectedNumberGy?.let { gy ->selectedNumberDy?.let { dy ->selectedNumberXl?.let { xl ->// 横向排列三个选择器Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceEvenly) {// 高压选择器NumberPickerComponent(value = gy,label = "收缩压",range = 80..200,onSave = { value ->coroutineScope.launch {//delay(300)withContext(Dispatchers.Main) {selectedNumberGy = value}withContext(Dispatchers.IO) {context.settingsDataStore.edit { settings ->settings[PreferencesKeys.NumbGy] = valueLog.d("NumberPickerDemo", "保存高压设置:$value")}}}})// 低压选择器NumberPickerComponent(value = dy,label = "舒张压",range = 50..150,onSave = { value ->coroutineScope.launch {//delay(300)withContext(Dispatchers.Main) {selectedNumberDy = value}withContext(Dispatchers.IO) {context.settingsDataStore.edit { settings ->settings[PreferencesKeys.NumbDy] = valueLog.d("NumberPickerDemo", "保存舒张压设置:$value")}}}})// 心率选择器NumberPickerComponent(value = xl,label = "心率",range = 40..200,onSave = { value ->coroutineScope.launch {//delay(300)withContext(Dispatchers.Main) {selectedNumberXl = value}withContext(Dispatchers.IO) {context.settingsDataStore.edit { settings ->settings[PreferencesKeys.NumbXl] = valueLog.d("NumberPickerDemo", "保存心率设置:$value")}}}})}val saveLock = remember { Any() } // 添加同步锁对象Button(onClick = {val now = System.currentTimeMillis()if (now - lastClickTime > 1000) {val date = selectedDateTime.format(dateFormatter)val time = selectedDateTime.format(timeFormatter)val high = selectedNumberGy ?: return@Buttonval low = selectedNumberDy ?: return@Buttonval heartRate = selectedNumberXl ?: return@Buttonval status = currentStatusTextlastClickTime = nowsynchronized(saveLock) {scope.launch(Dispatchers.IO){try {dbHelper.writableDatabase.use { db ->val values = ContentValues().apply {put("date", date)put("time", time)put("high", high)put("low", low)put("heart_rate", heartRate)put("status", status)}db.insertWithOnConflict("records",null,values,SQLiteDatabase.CONFLICT_REPLACE)}withContext(Dispatchers.Main) {//delay(300)Toast.makeText(context, "记录保存成功", Toast.LENGTH_SHORT).show()}} catch (e: Exception) {Log.e("Database", "保存失败", e)}}}}},modifier = Modifier.padding(vertical = 8.dp).width(200.dp)    // 加长按钮.height(48.dp),   // 增加高度shape = RoundedCornerShape(8.dp),colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF006400), // 使用深绿色配色contentColor = Color.White)) {Text("记 录",fontSize = 22.sp,  // 加大字号fontWeight = FontWeight.Medium)}Box(modifier = Modifier.fillMaxWidth().padding(16.dp).background(Color(0xFFE0F2F1), RoundedCornerShape(8.dp)).padding(16.dp)) {Text(text = when (currentStatusText) {"低血压" -> "收缩压<90,舒张压<60 ,一般无需治疗,若出现头晕、乏力等症状,建议就医。""正常血压" -> "90≤收缩压<120,60≤舒张压<80 ,无需治疗,保持健康生活方式(如低盐饮食、适量运动、戒烟限酒)。""正常高值血压" -> "120≤收缩压<140,80≤舒张压<90 ,注意饮食、运动和定期监测血压。建议生活方式干预,必要时咨询医生。""1级高血压" -> "140≤收缩压<160,90≤舒张压<100 ,改变生活方式(如减少盐摄入、增加运动),可能需要药物治疗。""2级高血压" -> "160≤收缩压<180,100≤舒张压<110 ,需要药物治疗并结合生活方式干预(如饮食调整、运动、减重)。""3级高血压" -> "180≤收缩压,110≤舒张压, 需紧急医疗干预,可能需要住院治疗。通常需要联合药物治疗。"else -> ""},color = Color.Black,fontSize = 20.sp)}}}} ?: run {CircularProgressIndicator()}// 显示日期和时间选择器Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceEvenly){Text(text = "日期: ${selectedDateTime.format(dateFormatter)}",style = MaterialTheme.typography.bodyLarge,fontSize = 20.sp, // 增大字体尺寸//fontWeight = FontWeight.Bold, // 加粗字体color = Color.DarkGray, // 使用更深的颜色modifier = Modifier.clickable { showDatePicker = true }.padding(8.dp))Text(text = "时间: ${selectedDateTime.format(timeFormatter)}",style = MaterialTheme.typography.bodyLarge,fontSize = 20.sp, // 增大字体尺寸//fontWeight = FontWeight.Bold, // 加粗字体color = Color.DarkGray, // 使用更深的颜色modifier = Modifier.clickable { showTimePicker = true }.padding(8.dp))// 日期选择器if (showDatePicker) {DatePickerDialog(onDismissRequest = { showDatePicker = false }, // 点击外部时关闭日期选择器onDateSelected = { date ->// 更新选中的日期selectedDateTime = selectedDateTime.withYear(date.year).withMonth(date.monthValue).withDayOfMonth(date.dayOfMonth)showDatePicker = false // 关闭日期选择器})}// 时间选择器if (showTimePicker) {TimePickerDialog(onDismissRequest = { showTimePicker = false }, // 点击外部时关闭时间选择器onTimeSelected = { time ->// 更新选中的时间selectedDateTime = selectedDateTime.withHour(time.hour).withMinute(time.minute)showTimePicker = false // 关闭时间选择器})}}}
}@Composable
private fun NumberPickerComponent(value: Int,label: String,range: IntRange,onSave: (Int) -> Unit
) {var currentValue by remember(value) { mutableStateOf(value) } // 添加当前值状态Column(horizontalAlignment = Alignment.CenterHorizontally) {Text(label, fontSize = 16.sp)NumberPicker(initialValue = value,range = range,onValueChange = { newValue ->if (newValue != currentValue) { // 只在数值变化时触发保存currentValue = newValueonSave(newValue)}})}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DatePickerDialog(onDismissRequest: () -> Unit,onDateSelected: (LocalDate) -> Unit
) {// 获取当前日期val currentDate = LocalDate.now()// 创建DatePicker状态,并初始化为当前日期val datePickerState = rememberDatePickerState(initialSelectedDateMillis = currentDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli())// 创建对话框Dialog(onDismissRequest = onDismissRequest,) {// 使用Column布局来组织对话框内容Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) {// 显示标题Text(text = "Select Date",style = MaterialTheme.typography.headlineSmall,modifier = Modifier.padding(bottom = 16.dp))// 显示日期选择器DatePicker(state = datePickerState)// 使用Row布局来组织按钮Row(modifier = Modifier.fillMaxWidth().padding(top = 16.dp),horizontalArrangement = Arrangement.End) {// 取消按钮Button(onClick = onDismissRequest,modifier = Modifier.padding(end = 8.dp)) {Text("Cancel")}// 确定按钮Button(onClick = {// 获取选中的日期val selectedDate = LocalDate.ofInstant(Instant.ofEpochMilli(datePickerState.selectedDateMillis ?: currentDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli()),ZoneId.systemDefault())// 调用回调函数,传递选中的日期onDateSelected(selectedDate)}) {Text("OK")}}}}
}@OptIn(ExperimentalMaterial3Api::class) // 使用实验性API的注解
@Composable // 标记为可组合函数
fun TimePickerDialog(onDismissRequest: () -> Unit, // 对话框关闭时的回调函数onTimeSelected: (LocalTime) -> Unit // 时间选择后的回调函数
) {val currentTime = LocalTime.now(ZoneId.systemDefault()) // 获取当前时间val timePickerState = rememberTimePickerState(initialHour = currentTime.hour, initialMinute = currentTime.minute) // 创建时间选择器的状态,并初始化为当前时间Dialog(onDismissRequest = onDismissRequest, // 设置对话框关闭的回调函数) {Column(modifier = Modifier.fillMaxWidth() // 填充父布局的宽度.padding(16.dp) // 设置内边距) {Text(text = "Select Time", // 显示文本style = MaterialTheme.typography.headlineSmall, // 使用主题中的小标题样式modifier = Modifier.padding(bottom = 16.dp) // 设置底部内边距)TimePicker(state = timePickerState) // 显示时间选择器Row(modifier = Modifier.fillMaxWidth() // 填充父布局的宽度.padding(top = 16.dp), // 设置顶部内边距horizontalArrangement = Arrangement.End // 水平排列方式为靠右) {Button(onClick = onDismissRequest, // 点击按钮时调用关闭回调函数modifier = Modifier.padding(end = 8.dp) // 设置右边距) {Text("Cancel") // 显示取消文本}Button(onClick = {val selectedTime = LocalTime.of(timePickerState.hour, timePickerState.minute) // 获取选中的时间onTimeSelected(selectedTime) // 调用时间选择后的回调函数}) {Text("OK") // 显示确定文本}}}}
}@Composable
fun BottomNavigationExample() {val context = LocalContext.currentval activity = context as Activity // 直接转换为 Activityval dbHelper = remember { RecordDbHelper(context) }var selectedItem by rememberSaveable { mutableStateOf(0) }val historyStack = remember { mutableStateListOf<Int>() }val originalGreen = Color(0xFFE8F5E9)// 加深方案(任选其一)val deepGreen1 = Color(0xFFC8E6C9)  // 浅灰绿(比原色深10%)val deepGreen2 = Color(0xFFA5D6A7)  // 中等青绿(Material Teal 200)val deepGreen3 = Color(0xFF80CBC4)  // 深青蓝色(Material Teal 300)val gradientColors = listOf(deepGreen2, deepGreen3)// 处理返回键BackHandler(enabled = historyStack.isNotEmpty()) {if (historyStack.isNotEmpty()) {// 兼容性写法(支持所有 Kotlin 版本)val lastIndex = historyStack.size - 1selectedItem = historyStack.removeAt(lastIndex)} else {activity.finish() // 正确调用 Activity 的 finish()}}// 点击底部导航项时更新历史栈fun onTabSelected(index: Int) {historyStack.add(selectedItem)selectedItem = index}val items = listOf("记录", "历史", "图表")// 使用Scaffold布局,包含底部导航栏Scaffold(bottomBar = {// 创建底部导航栏NavigationBar(modifier = Modifier//.height(72.dp) // 保持高度设置.padding(horizontal = 8.dp).background(brush = Brush.linearGradient(colors = gradientColors,start = Offset(0f, 0f),end = Offset(1000f, 0f)),alpha = 0.9f  // 添加背景透明度),containerColor = Color.Transparent) {// 遍历items列表,为每个项创建一个NavigationBarItemitems.forEachIndexed { index, item ->NavigationBarItem(// 根据index选择不同的图标icon = {Icon(painter = painterResource(id = when (index) {0 -> R.drawable.write  // 修正资源引用(去掉_png后缀)1 -> R.drawable.list // 修正资源引用(去掉_png后缀)else -> R.drawable.chart2}),contentDescription = item,modifier = Modifier.size(48.dp),//.background(Color.Red)tint = Color.Unspecified)},// 显示项的标签label = { Text(item,fontSize = 12.sp,color = Color.Black,  // 强制文字颜色为白色modifier = Modifier.padding(top = 0.dp)//modifier = Modifier.padding(vertical = 2.dp))  },// 判断当前项是否被选中selected = selectedItem == index,onClick = { onTabSelected(index) },colors = NavigationBarItemDefaults.colors(selectedIconColor = Color.White,indicatorColor = Color(0xFF006400).copy(alpha = 0.5f)))}}}) { innerPadding ->// 根据选中的项显示不同的内容when (selectedItem) {0 -> Box(modifier = Modifier.fillMaxSize().background(brush = Brush.verticalGradient(colors = gradientColors,startY = 0f,endY = 1200f)).padding(innerPadding)  // 添加内边距) {NumberPickerDemo(dbHelper = dbHelper)}1 -> Box(modifier = Modifier.fillMaxSize().background(brush = Brush.verticalGradient(  // 历史界面也改为渐变背景colors = gradientColors,startY = 0f,endY = 1200f)).padding(top = 20.dp)  // 新增顶部内边距.padding(innerPadding)  // 添加内边距){HistoryScreen(dbHelper = dbHelper)}2 -> Box(modifier = Modifier.fillMaxSize().background(brush = Brush.verticalGradient(  // 统计界面改为渐变背景colors = gradientColors,startY = 0f,endY = 1200f)).padding(innerPadding)  // 添加内边距){StatisticsScreen(dbHelper = dbHelper)}}}
}@Composable
fun HistoryScreen(dbHelper: RecordDbHelper) {val records = remember { mutableStateListOf<HealthRecord>() }var showDeleteDialog by remember { mutableStateOf(false) }var selectedRecord by remember { mutableStateOf<HealthRecord?>(null) }val scope = rememberCoroutineScope()// 加载数据库记录LaunchedEffect(Unit) {scope.launch(Dispatchers.IO) {try {val loadedRecords = mutableListOf<HealthRecord>()dbHelper.readableDatabase.use { db ->val cursor = db.query("records",arrayOf("date", "time", "high", "low", "heart_rate", "status"),null, null, null, null,"date DESC, time DESC")try {while (cursor.moveToNext()) {val date = cursor.getString(0) ?: ""val time = cursor.getString(1) ?: ""val high = cursor.getInt(2)val low = cursor.getInt(3)val heartRate = cursor.getInt(4)val status = cursor.getString(5) ?: "未知"loadedRecords.add(HealthRecord(date, time, high, low, heartRate, status))}} finally {cursor.close()}}withContext(Dispatchers.Main) {records.clear()records.addAll(loadedRecords)}} catch (e: Exception) {Log.e("HistoryScreen", "加载记录失败: ${e.message}", e)}}}// 删除确认对话框if (showDeleteDialog) {AlertDialog(onDismissRequest = { showDeleteDialog = false },title = { Text("删除记录") },text = { Text("确定要删除这条记录吗?") },confirmButton = {TextButton(onClick = {selectedRecord?.let { record ->scope.launch(Dispatchers.IO) {try {dbHelper.writableDatabase.delete("records","date = ? AND time = ?",arrayOf(record.date, record.time))withContext(Dispatchers.Main) {records.remove(record)showDeleteDialog = false}} catch (e: Exception) {Log.e("HistoryScreen", "删除失败: ${e.message}", e)}}}}) { Text("确认") }},dismissButton = {TextButton(onClick = { showDeleteDialog = false }) { Text("取消") }})}// 记录列表LazyColumn(modifier = Modifier.fillMaxSize(),horizontalAlignment = Alignment.CenterHorizontally) {items(count = records.size,key = { index -> "${records[index].date}_${records[index].time}" }) { index ->val record = records[index]Card(modifier = Modifier.fillMaxWidth(0.9f).padding(vertical = 2.dp).clickable {selectedRecord = recordshowDeleteDialog = true},elevation = CardDefaults.cardElevation(4.dp),colors = CardDefaults.cardColors(containerColor = when (record.status) {"低血压" -> Color(0xFFE3F2FD)"正常血压" -> Color(0xFFE8F5E9)"正常高值血压" -> Color(0xFFFFF8E1)"1级高血压" -> Color(0xFFFFF3E0)"2级高血压", "3级高血压" -> Color(0xFFFFEBEE)else -> Color.White})) {Column(modifier = Modifier.padding(16.dp)) {Row(modifier = Modifier.fillMaxWidth().padding(top = 16.dp)) {Text("日期: ${record.date} ${record.time}",fontSize = 16.sp,modifier = Modifier.weight(1f))Text("状态: ${record.status}",color = when (record.status) {"低血压" -> Color.Blue"正常血压" -> Color(0xFF006400)"正常高值血压" -> Color(0xFFFFB300)"1级高血压" -> Color(0xFFFF6700)"2级高血压", "3级高血压" -> Color.Redelse -> Color.Gray},fontSize = 18.sp)}Row(modifier = Modifier.fillMaxWidth().padding(top = 16.dp)) {Text("血压: ${record.high}/${record.low} mmHg",fontSize = 18.sp,modifier = Modifier.weight(1f))Text("心率: ${record.heartRate} 次/分钟",fontSize = 18.sp)}}}}}
}
@Composable
fun StatisticsScreen(dbHelper: RecordDbHelper) {val context = LocalContext.currentval records = remember { mutableStateListOf<HealthRecord>() }val isLoading = remember { mutableStateOf(true) }// 加载数据LaunchedEffect(Unit) {withContext(Dispatchers.IO) {val tempList = dbHelper.readableDatabase.use { db ->db.query("records",arrayOf("date", "time", "high", "low", "heart_rate"),null, null, null, null,"date || time ASC").use { cursor ->val list = mutableListOf<HealthRecord>()while (cursor.moveToNext()) {list.add(HealthRecord(date = cursor.getString(0),time = cursor.getString(1),high = cursor.getInt(2),low = cursor.getInt(3),heartRate = cursor.getInt(4),status = ""))}list}}withContext(Dispatchers.Main) {records.clear()records.addAll(tempList)isLoading.value = false}}}// 加载指示器if (isLoading.value) {Box(modifier = Modifier.fillMaxSize(),contentAlignment = Alignment.Center) {CircularProgressIndicator()}return}// 图表视图AndroidView(factory = { context ->LineChart(context).apply {layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)setTouchEnabled(true)setPinchZoom(true)description.isEnabled = false// X轴配置xAxis.apply {position = XAxis.XAxisPosition.BOTTOMgranularity = 1flabelRotationAngle = -45fvalueFormatter = object : ValueFormatter() {override fun getFormattedValue(value: Float): String {return records.getOrNull(value.toInt())?.let {"${it.date}\n${it.time}"} ?: ""}}setLabelCount(5, true)}// Y轴配置axisLeft.apply {granularity = 20faxisMinimum = 0faxisMaximum = 220faddLimitLine(LimitLine(90f, "收缩压阈值").apply {lineColor = Color.Red.hashCode()lineWidth = 2fenableDashedLine(10f, 10f, 0f)})addLimitLine(LimitLine(140f, "舒张压阈值").apply {lineColor = Color.Red.hashCode()lineWidth = 2fenableDashedLine(10f, 10f, 0f)})}axisRight.isEnabled = falselegend.apply {verticalAlignment = Legend.LegendVerticalAlignment.BOTTOMhorizontalAlignment = Legend.LegendHorizontalAlignment.CENTERorientation = Legend.LegendOrientation.HORIZONTALsetDrawInside(false)yOffset = 20f}}},update = { chart ->try {if (records.isNotEmpty()) {val highEntries = mutableListOf<Entry>()val lowEntries = mutableListOf<Entry>()val heartEntries = mutableListOf<Entry>()records.forEachIndexed { index, record ->highEntries.add(Entry(index.toFloat(), record.high.toFloat()))lowEntries.add(Entry(index.toFloat(), record.low.toFloat()))heartEntries.add(Entry(index.toFloat(), record.heartRate.toFloat()))}val highSet = LineDataSet(highEntries, "收缩压").apply {color = Color.Red.hashCode()lineWidth = 2fsetDrawCircles(false)}val lowSet = LineDataSet(lowEntries, "舒张压").apply {color = Color.Blue.hashCode()lineWidth = 2fsetDrawCircles(false)}val heartSet = LineDataSet(heartEntries, "心率").apply {color = Color.Green.hashCode()lineWidth = 2fsetDrawCircles(false)}chart.data = LineData(highSet, lowSet, heartSet)chart.animateY(1000)chart.invalidate()chart.setVisibleXRangeMaximum(7f)chart.moveViewToX((records.size - 1).toFloat())}} catch (e: Exception) {Log.e("ChartUpdate", "更新图表失败: ${e.message}", e)}},modifier = Modifier.fillMaxSize().padding(16.dp))
}

settings.gradle.kts 配置如下:

pluginManagement {repositories {google {content {includeGroupByRegex("com\\.android.*")includeGroupByRegex("com\\.google.*")includeGroupByRegex("androidx.*")}}mavenCentral()gradlePluginPortal()}
}
dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {google()mavenCentral()maven {url = uri("https://jitpack.io")}}
}rootProject.name = "MyNumSet"
include(":app")

build.gradle.kts配置如下:

plugins {alias(libs.plugins.android.application)alias(libs.plugins.kotlin.android)alias(libs.plugins.kotlin.compose)
}android {namespace = "com.example.mynumset"compileSdk = 35defaultConfig {applicationId = "com.example.mynumset"minSdk = 34targetSdk = 35versionCode = 1versionName = "1.0"testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {isMinifyEnabled = falseproguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),"proguard-rules.pro")}}compileOptions {sourceCompatibility = JavaVersion.VERSION_11targetCompatibility = JavaVersion.VERSION_11}kotlinOptions {jvmTarget = "11"}buildFeatures {compose = true}
}dependencies {implementation ("com.github.PhilJay:MPAndroidChart:v3.1.0")implementation ("androidx.datastore:datastore-preferences:1.0.0")implementation("androidx.compose.foundation:foundation:1.4.0")implementation(libs.androidx.core.ktx)implementation(libs.androidx.lifecycle.runtime.ktx)implementation(libs.androidx.activity.compose)implementation(platform(libs.androidx.compose.bom))implementation(libs.androidx.ui)implementation(libs.androidx.ui.graphics)implementation(libs.androidx.ui.tooling.preview)implementation(libs.androidx.material3)testImplementation(libs.junit)androidTestImplementation(libs.androidx.junit)androidTestImplementation(libs.androidx.espresso.core)androidTestImplementation(platform(libs.androidx.compose.bom))androidTestImplementation(libs.androidx.ui.test.junit4)debugImplementation(libs.androidx.ui.tooling)debugImplementation(libs.androidx.ui.test.manifest)
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com