From bb096bb5b1733ef33042eac4d5c9ad5756568e93 Mon Sep 17 00:00:00 2001 From: zzh Date: Fri, 24 Jul 2026 17:35:19 +0800 Subject: [PATCH] Optimize dashboard environment cards --- .../com/example/smarthome/ui/MainScaffold.kt | 507 ++++++++++++------ 1 file changed, 333 insertions(+), 174 deletions(-) diff --git a/app/src/main/java/com/example/smarthome/ui/MainScaffold.kt b/app/src/main/java/com/example/smarthome/ui/MainScaffold.kt index 1b5e49e..947f070 100644 --- a/app/src/main/java/com/example/smarthome/ui/MainScaffold.kt +++ b/app/src/main/java/com/example/smarthome/ui/MainScaffold.kt @@ -210,34 +210,72 @@ fun RoomSelector( modifier = Modifier .fillMaxWidth() .horizontalScroll(rememberScrollState()), - horizontalArrangement = Arrangement.spacedBy(12.dp) + horizontalArrangement = Arrangement.spacedBy(10.dp) ) { rooms.forEachIndexed { index, room -> val isSelected = index == selectedRoom + val shape = RoundedCornerShape(18.dp) Box( modifier = Modifier - .width(128.dp) - .height(72.dp) - .clip(RoundedCornerShape(16.dp)) + .widthIn(min = 92.dp) + .height(52.dp) + .clip(shape) .background( - if (isSelected) Color(0xFF00D1FF).copy(alpha = 0.22f) - else Color(0xFF1A1A1A).copy(alpha = 0.55f) + if (isSelected) { + Brush.linearGradient( + listOf( + Color(0xFF00D1FF).copy(alpha = 0.36f), + Color(0xFFB89CFF).copy(alpha = 0.28f) + ) + ) + } else { + Brush.linearGradient( + listOf( + Color.White.copy(alpha = 0.10f), + Color(0xFF121212).copy(alpha = 0.38f) + ) + ) + } ) .border( - width = 1.dp, - color = if (isSelected) Color(0xFF00D1FF) else Color.White.copy(alpha = 0.15f), - shape = RoundedCornerShape(16.dp) + width = if (isSelected) 1.5.dp else 1.dp, + color = if (isSelected) Color(0xFFA9F0FF) else Color.White.copy(alpha = 0.16f), + shape = shape ) .clickable { onRoomSelect(index) } - .padding(14.dp), - contentAlignment = Alignment.CenterStart + .padding(horizontal = 16.dp), + contentAlignment = Alignment.Center ) { - Column { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Box( + modifier = Modifier + .size(if (isSelected) 7.dp else 5.dp) + .clip(CircleShape) + .background( + if (isSelected) Color(0xFFA9F0FF) + else Color.White.copy(alpha = 0.36f) + ) + ) Text( text = room, - color = Color.White, - fontSize = 16.sp, - fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Medium + color = if (isSelected) Color.White else Color.White.copy(alpha = 0.72f), + fontSize = 15.sp, + fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Medium, + maxLines = 1 + ) + } + + if (isSelected) { + Box( + modifier = Modifier + .align(Alignment.BottomCenter) + .width(28.dp) + .height(3.dp) + .clip(RoundedCornerShape(2.dp)) + .background(Color(0xFFA9F0FF)) ) } } @@ -426,67 +464,87 @@ fun OverviewEnvironmentPanel(modifier: Modifier = Modifier) { Box( modifier = modifier .clip(RoundedCornerShape(24.dp)) - .background(Color(0xFF1A1A1A).copy(alpha = 0.55f)) + .background( + Brush.linearGradient( + listOf( + Color(0xFF1A1A1A).copy(alpha = 0.64f), + Color(0xFF101820).copy(alpha = 0.48f) + ) + ) + ) .border( width = 1.dp, - color = Color.White.copy(alpha = 0.15f), + color = Color.White.copy(alpha = 0.18f), shape = RoundedCornerShape(24.dp) ) - .padding(20.dp) + .padding(16.dp) ) { Column( modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(12.dp) + verticalArrangement = Arrangement.spacedBy(8.dp) ) { - Text( - text = "环境总览", - fontWeight = FontWeight.Bold, - color = Color.White, - fontSize = 18.sp + OverviewPanelHeader( + title = "环境总览", + subtitle = "全屋加权平均 · 综合环境水平", + statusText = "舒适", + statusColor = Color(0xFF00E676) ) - Text( - text = "全屋加权平均 · 综合环境水平", - color = Color(0xFF9AA0A6), - fontSize = 12.sp - ) - Row( + Column( modifier = Modifier .fillMaxWidth() .weight(1f), - horizontalArrangement = Arrangement.spacedBy(12.dp) + verticalArrangement = Arrangement.spacedBy(8.dp) ) { - EnvironmentCard( - icon = "🌡️", - iconColor = Color(0xFF00E676), - value = "24.0", - unit = "°C", - label = "加权平均温度", - modifier = Modifier.weight(1f).fillMaxHeight() - ) - EnvironmentCard( - icon = "💧", - iconColor = Color(0xFF00E676), - value = "65", - unit = "%", - label = "加权平均湿度", - modifier = Modifier.weight(1f).fillMaxHeight() - ) - EnvironmentCard( - icon = "😊", - iconColor = Color(0xFF00E676), - value = "420", - unit = "ppm", - label = "加权平均 CO₂", - modifier = Modifier.weight(1f).fillMaxHeight() - ) - EnvironmentCard( - icon = "✨", - iconColor = Color(0xFFA9F0FF), - value = "0.18", - unit = "mg/m³", - label = "加权平均 TVOC", - modifier = Modifier.weight(1f).fillMaxHeight() - ) + Row( + modifier = Modifier.weight(1f), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + EnvironmentCard( + icon = "🌡️", + iconColor = Color(0xFF00E676), + name = "温度", + value = "24.0", + unit = "°C", + label = "全屋平均", + status = "舒适", + modifier = Modifier.weight(1f).fillMaxHeight() + ) + EnvironmentCard( + icon = "💧", + iconColor = Color(0xFF4DD0E1), + name = "湿度", + value = "65", + unit = "%", + label = "全屋平均", + status = "略湿", + modifier = Modifier.weight(1f).fillMaxHeight() + ) + } + Row( + modifier = Modifier.weight(1f), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + EnvironmentCard( + icon = "◎", + iconColor = Color(0xFF00E676), + name = "CO₂", + value = "420", + unit = "ppm", + label = "二氧化碳", + status = "清新", + modifier = Modifier.weight(1f).fillMaxHeight() + ) + EnvironmentCard( + icon = "✦", + iconColor = Color(0xFFA9F0FF), + name = "TVOC", + value = "0.18", + unit = "mg/m³", + label = "挥发性有机物", + status = "正常", + modifier = Modifier.weight(1f).fillMaxHeight() + ) + } } } } @@ -497,111 +555,196 @@ fun HealthSafetyPanel(modifier: Modifier = Modifier) { Box( modifier = modifier .clip(RoundedCornerShape(24.dp)) - .background(Color(0xFF1A1A1A).copy(alpha = 0.55f)) + .background( + Brush.linearGradient( + listOf( + Color(0xFF1A1A1A).copy(alpha = 0.64f), + Color(0xFF1C1514).copy(alpha = 0.46f) + ) + ) + ) .border( width = 1.dp, - color = Color.White.copy(alpha = 0.15f), + color = Color.White.copy(alpha = 0.18f), shape = RoundedCornerShape(24.dp) ) - .padding(20.dp) + .padding(16.dp) ) { Column( modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(12.dp) + verticalArrangement = Arrangement.spacedBy(8.dp) ) { - Text( - text = "健康与安全", - fontWeight = FontWeight.Bold, - color = Color.White, - fontSize = 18.sp - ) - Text( - text = "传感器2单点实测 · 最不利点状态", - color = Color(0xFF9AA0A6), - fontSize = 12.sp + OverviewPanelHeader( + title = "健康与安全", + subtitle = "传感器2单点实测 · 最不利点状态", + statusText = "需关注", + statusColor = Color(0xFFFFB74D) ) Row( modifier = Modifier .fillMaxWidth() .weight(1f), - horizontalArrangement = Arrangement.spacedBy(12.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - EnvironmentCard( - icon = "💨", - iconColor = Color(0xFFFFB74D), - value = "35", - unit = "μg/m³", - label = "PM2.5 · 传感器2", - modifier = Modifier.weight(1f).fillMaxHeight() - ) - EnvironmentCard( - icon = "⚠️", - iconColor = Color(0xFFFFB74D), - value = "0.03", - unit = "mg/m³", - label = "甲醛 · 传感器2", - modifier = Modifier.weight(1f).fillMaxHeight() - ) - CondensationMonitorCard(modifier = Modifier.weight(1.35f).fillMaxHeight()) + Row( + modifier = Modifier.weight(1.15f).fillMaxHeight(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + EnvironmentCard( + icon = "≈", + iconColor = Color(0xFFFFB74D), + name = "PM2.5", + value = "35", + unit = "μg/m³", + label = "细颗粒物 · 传感器2", + status = "良", + modifier = Modifier.weight(1f).fillMaxHeight() + ) + EnvironmentCard( + icon = "!", + iconColor = Color(0xFFFFB74D), + name = "甲醛", + value = "0.03", + unit = "mg/m³", + label = "HCHO · 传感器2", + status = "安全", + modifier = Modifier.weight(1f).fillMaxHeight() + ) + } + CondensationMonitorCard(modifier = Modifier.weight(1f).fillMaxHeight()) } } } } +@Composable +private fun OverviewPanelHeader( + title: String, + subtitle: String, + statusText: String, + statusColor: Color +) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { + Text( + text = title, + fontWeight = FontWeight.Bold, + color = Color.White, + fontSize = 16.sp + ) + Text( + text = subtitle, + color = Color(0xFF9AA0A6), + fontSize = 10.sp, + maxLines = 1 + ) + } + Row( + modifier = Modifier + .clip(RoundedCornerShape(50)) + .background(statusColor.copy(alpha = 0.14f)) + .border( + width = 1.dp, + color = statusColor.copy(alpha = 0.42f), + shape = RoundedCornerShape(50) + ) + .padding(horizontal = 8.dp, vertical = 4.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(5.dp) + ) { + Box( + modifier = Modifier + .size(6.dp) + .clip(CircleShape) + .background(statusColor) + ) + Text( + text = statusText, + color = statusColor, + fontSize = 11.sp, + fontWeight = FontWeight.SemiBold + ) + } + } +} + @Composable private fun CondensationMonitorCard(modifier: Modifier = Modifier) { Box( modifier = modifier .clip(RoundedCornerShape(20.dp)) - .background(Color(0xFF00D1FF).copy(alpha = 0.12f)) + .background( + Brush.linearGradient( + listOf( + Color(0xFF00D1FF).copy(alpha = 0.20f), + Color(0xFF121212).copy(alpha = 0.42f) + ) + ) + ) .border( width = 1.5.dp, color = Color(0xFF00D1FF).copy(alpha = 0.75f), shape = RoundedCornerShape(20.dp) ) - .padding(16.dp) + .padding(horizontal = 10.dp, vertical = 8.dp) ) { - Column( + Row( modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.SpaceBetween + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.Top + Box( + modifier = Modifier + .size(28.dp) + .clip(RoundedCornerShape(9.dp)) + .background(Color(0xFF00D1FF).copy(alpha = 0.18f)), + contentAlignment = Alignment.Center ) { - Text(text = "🧱", fontSize = 22.sp) - Box( - modifier = Modifier - .size(8.dp) - .clip(CircleShape) - .background(Color(0xFF00E676)) - ) + Text(text = "▦", fontSize = 14.sp, color = Color(0xFFA9F0FF)) } - Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { - Text( - text = "18.6", - fontSize = 36.sp, - fontWeight = FontWeight.Light, - color = Color.White - ) - Text( - text = "°C", - fontSize = 14.sp, - color = Color(0xFF9AA0A6) - ) + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(1.dp) + ) { Text( text = "防结露监控", - fontSize = 12.sp, - fontWeight = FontWeight.Bold, - color = Color(0xFF00D1FF) - ) - Text( - text = "墙温 · 安全", fontSize = 11.sp, - color = Color(0xFF9AA0A6) + fontWeight = FontWeight.Bold, + color = Color.White, + maxLines = 1 ) + Row( + verticalAlignment = Alignment.Bottom, + horizontalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = "18.6", + fontSize = 18.sp, + fontWeight = FontWeight.Light, + color = Color.White + ) + Text( + text = "°C", + fontSize = 9.sp, + color = Color(0xFF9AA0A6), + modifier = Modifier.padding(bottom = 3.dp) + ) + } } + Text( + text = "安全", + color = Color(0xFF00E676), + fontSize = 9.sp, + fontWeight = FontWeight.SemiBold, + modifier = Modifier + .clip(RoundedCornerShape(50)) + .background(Color(0xFF00E676).copy(alpha = 0.14f)) + .padding(horizontal = 6.dp, vertical = 2.dp) + ) } } } @@ -1921,6 +2064,7 @@ fun AirConditionerCard( EnvironmentCard( icon = "🌡️", iconColor = Color(0xFF00E676), + name = "温度", value = "${currentTemp.value}", unit = "°C", label = "TEMPERATURE", @@ -1933,6 +2077,7 @@ fun AirConditionerCard( EnvironmentCard( icon = "💧", iconColor = Color(0xFF00E676), + name = "湿度", value = "${humidity.value}", unit = "%", label = "HUMIDITY", @@ -1945,6 +2090,7 @@ fun AirConditionerCard( EnvironmentCard( icon = "💨", iconColor = Color(0xFFFFB74D), + name = "PM2.5", value = "${pm25.value}", unit = "μg/m³", label = "PM 2.5", @@ -1957,6 +2103,7 @@ fun AirConditionerCard( EnvironmentCard( icon = "😊", iconColor = Color(0xFF00E676), + name = "CO₂", value = "${co2.value}", unit = "ppm", label = "CO2", @@ -1973,9 +2120,11 @@ fun AirConditionerCard( private fun EnvironmentCard( icon: String, iconColor: Color, + name: String, value: String, unit: String, label: String, + status: String = "", modifier: Modifier = Modifier ) { Box( @@ -1984,79 +2133,89 @@ private fun EnvironmentCard( .background( Brush.linearGradient( listOf( - Color.Black.copy(alpha = 0.5f), - Color.Black.copy(alpha = 0.4f) + Color.White.copy(alpha = 0.10f), + Color.Black.copy(alpha = 0.42f) ) ) ) .border( - width = 0.5.dp, - color = Color.White.copy(alpha = 0.15f), + width = 1.dp, + color = Color.White.copy(alpha = 0.14f), shape = RoundedCornerShape(20.dp) ) - .padding(16.dp) + .padding(horizontal = 10.dp, vertical = 8.dp) ) { - Column( + Row( modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.SpaceBetween + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - // 顶部:图标和指示灯 - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.Top + Box( + modifier = Modifier + .size(28.dp) + .clip(RoundedCornerShape(9.dp)) + .background(iconColor.copy(alpha = 0.16f)) + .border( + width = 1.dp, + color = iconColor.copy(alpha = 0.24f), + shape = RoundedCornerShape(9.dp) + ), + contentAlignment = Alignment.Center ) { - // 图标 - Box( - modifier = Modifier - .size(44.dp) - .clip(RoundedCornerShape(12.dp)) - .background(iconColor.copy(alpha = 0.15f)), - contentAlignment = Alignment.Center - ) { - Text( - text = icon, - fontSize = 22.sp - ) - } - - // 指示灯 - Box( - modifier = Modifier - .size(8.dp) - .clip(RoundedCornerShape(4.dp)) - .background(iconColor) + Text( + text = icon, + fontSize = 14.sp, + color = iconColor ) } - - // 中间:数值 + Column( - verticalArrangement = Arrangement.spacedBy(4.dp) + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(1.dp) ) { + Text( + text = name, + fontSize = 11.sp, + fontWeight = FontWeight.Bold, + color = Color.White, + maxLines = 1 + ) Row( verticalAlignment = Alignment.Bottom, - horizontalArrangement = Arrangement.spacedBy(4.dp) + horizontalArrangement = Arrangement.spacedBy(3.dp) ) { Text( text = value, - fontSize = 36.sp, + fontSize = 18.sp, fontWeight = FontWeight.Light, color = Color.White ) Text( text = unit, - fontSize = 14.sp, + fontSize = 9.sp, color = Color(0xFF9AA0A6), - modifier = Modifier.padding(bottom = 6.dp) + modifier = Modifier.padding(bottom = 3.dp) ) } - - // 底部:标签 + } + + if (status.isNotEmpty()) { Text( - text = label, - fontSize = 11.sp, - color = Color(0xFF9AA0A6), - letterSpacing = 0.5.sp + text = status, + color = iconColor, + fontSize = 9.sp, + fontWeight = FontWeight.SemiBold, + modifier = Modifier + .clip(RoundedCornerShape(50)) + .background(iconColor.copy(alpha = 0.12f)) + .padding(horizontal = 6.dp, vertical = 2.dp) + ) + } else { + Box( + modifier = Modifier + .size(7.dp) + .clip(RoundedCornerShape(4.dp)) + .background(iconColor) ) } }