From db6a7978a959c29286386e7c94255af772d11e23 Mon Sep 17 00:00:00 2001 From: KremeCN <3265494849@qq.com> Date: Tue, 25 Aug 2026 16:21:16 +0800 Subject: [PATCH] fix(scene): simplify card styling to flat outlined cards without nested double shells --- .../manager/ui/scene/SceneEditorScreen.kt | 37 ++++--- .../manager/ui/scene/SceneExecutionScreen.kt | 20 ++-- .../abox/manager/ui/scene/SceneListScreen.kt | 100 ++++++++---------- 3 files changed, 80 insertions(+), 77 deletions(-) diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneEditorScreen.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneEditorScreen.kt index 0a98780..95d2cfe 100644 --- a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneEditorScreen.kt +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneEditorScreen.kt @@ -1,6 +1,7 @@ package com.flagship.abox.manager.ui.scene import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable @@ -41,6 +42,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.OutlinedCard import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Slider @@ -157,10 +159,11 @@ fun SceneEditorScreen( verticalArrangement = Arrangement.spacedBy(14.dp), ) { item(key = "title_card") { - Card( + OutlinedCard( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)), + colors = CardDefaults.outlinedCardColors(containerColor = MaterialTheme.colorScheme.surface), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)), ) { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) { OutlinedTextField( @@ -188,10 +191,11 @@ fun SceneEditorScreen( if (state.type == AutomationType.AUTOMATIC) { item(key = "triggers_card") { - Card( + OutlinedCard( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)), + colors = CardDefaults.outlinedCardColors(containerColor = MaterialTheme.colorScheme.surface), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)), ) { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) { Row( @@ -237,10 +241,11 @@ fun SceneEditorScreen( } item(key = "conditions_card") { - Card( + OutlinedCard( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)), + colors = CardDefaults.outlinedCardColors(containerColor = MaterialTheme.colorScheme.surface), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)), ) { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) { Row( @@ -285,10 +290,11 @@ fun SceneEditorScreen( } item(key = "actions_header") { - Card( + OutlinedCard( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)), + colors = CardDefaults.outlinedCardColors(containerColor = MaterialTheme.colorScheme.surface), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)), ) { Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) { Row( @@ -353,10 +359,11 @@ fun SceneEditorScreen( } item(key = "advanced_options") { - Card( + OutlinedCard( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)), + colors = CardDefaults.outlinedCardColors(containerColor = MaterialTheme.colorScheme.surface), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)), ) { Column(modifier = Modifier.padding(16.dp)) { Row( @@ -416,10 +423,11 @@ fun SceneEditorScreen( } item(key = "other_options") { - Card( + OutlinedCard( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f)), + colors = CardDefaults.outlinedCardColors(containerColor = MaterialTheme.colorScheme.surface), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)), ) { Column(modifier = Modifier.padding(16.dp)) { Row( @@ -637,10 +645,11 @@ private fun ActionCardRow( onMoveDown: (Int) -> Unit, onRemove: () -> Unit, ) { - Card( + OutlinedCard( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(12.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface), + colors = CardDefaults.outlinedCardColors(containerColor = MaterialTheme.colorScheme.surface), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)), ) { Row( modifier = Modifier diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneExecutionScreen.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneExecutionScreen.kt index c21663c..a6dd083 100644 --- a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneExecutionScreen.kt +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneExecutionScreen.kt @@ -1,5 +1,6 @@ package com.flagship.abox.manager.ui.scene +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -32,6 +33,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -184,16 +186,21 @@ private fun CompletedContent( verticalArrangement = Arrangement.spacedBy(12.dp), ) { item(key = "summary") { - Card( + OutlinedCard( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), - colors = CardDefaults.cardColors( + colors = CardDefaults.outlinedCardColors( containerColor = if (result.allSucceeded) { - MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.5f) + MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.3f) } else { - MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.5f) + MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.3f) }, ), + border = BorderStroke( + 1.dp, + if (result.allSucceeded) MaterialTheme.colorScheme.primary.copy(alpha = 0.4f) + else MaterialTheme.colorScheme.error.copy(alpha = 0.4f), + ), ) { Column(modifier = Modifier.padding(16.dp)) { Text( @@ -256,10 +263,11 @@ private fun CompletedContent( @Composable private fun ActionResultRow(stepNumber: Int, entry: SceneActionExecutionResult) { - Card( + OutlinedCard( modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(12.dp), - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface), + colors = CardDefaults.outlinedCardColors(containerColor = MaterialTheme.colorScheme.surface), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)), ) { Row( modifier = Modifier diff --git a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneListScreen.kt b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneListScreen.kt index d23f7af..8130cbd 100644 --- a/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneListScreen.kt +++ b/android/app/src/main/kotlin/com/flagship/abox/manager/ui/scene/SceneListScreen.kt @@ -1,6 +1,7 @@ package com.flagship.abox.manager.ui.scene import android.widget.Toast +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -17,7 +18,6 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add @@ -27,7 +27,6 @@ import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.outlined.Bolt import androidx.compose.material.icons.outlined.Schedule import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem @@ -37,6 +36,7 @@ import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Scaffold import androidx.compose.material3.SecondaryTabRow import androidx.compose.material3.Surface @@ -95,6 +95,7 @@ fun SceneListScreen( } Scaffold( + containerColor = Color.Transparent, floatingActionButton = { Box { ExtendedFloatingActionButton( @@ -145,6 +146,8 @@ fun SceneListScreen( item(key = "tabs") { SecondaryTabRow( selectedTabIndex = selectedTab.ordinal, + containerColor = Color.Transparent, + divider = {}, modifier = Modifier.fillMaxWidth().clip(RoundedCornerShape(12.dp)), ) { SceneFilterTab.entries.forEach { tab -> @@ -219,17 +222,20 @@ private fun SceneCard( onEdit: () -> Unit, onDelete: () -> Unit, ) { - Card( - modifier = Modifier.fillMaxWidth(), - elevation = CardDefaults.cardElevation(defaultElevation = 2.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f), + val accentColor = scene.color.toColorOrNull() ?: MaterialTheme.colorScheme.primary + + OutlinedCard( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick), + shape = RoundedCornerShape(16.dp), + colors = CardDefaults.outlinedCardColors( + containerColor = MaterialTheme.colorScheme.surface, ), + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)), ) { Column( - modifier = Modifier - .clickable(onClick = onClick) - .padding(16.dp), + modifier = Modifier.padding(16.dp), ) { Row( verticalAlignment = Alignment.CenterVertically, @@ -239,7 +245,7 @@ private fun SceneCard( modifier = Modifier .size(44.dp) .background( - color = scene.color.toColorOrNull() ?: MaterialTheme.colorScheme.primary, + color = accentColor.copy(alpha = 0.12f), shape = RoundedCornerShape(12.dp), ), contentAlignment = Alignment.Center, @@ -284,40 +290,30 @@ private fun SceneCard( } } - Spacer(Modifier.height(10.dp)) + Spacer(Modifier.height(12.dp)) - // Trigger & Action summary pills + // Trigger & Action summary and controls Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, ) { + // Summary text without nested heavy container shells Row( - horizontalArrangement = Arrangement.spacedBy(6.dp), verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp), ) { - if (scene.type == AutomationType.AUTOMATIC && scene.triggers.isNotEmpty()) { - Surface( - shape = RoundedCornerShape(6.dp), - color = MaterialTheme.colorScheme.tertiaryContainer, - ) { - Text( - text = "⚡ ${scene.triggers.size} 触发器", - modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp), - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onTertiaryContainer, - ) - } - } - Surface( - shape = RoundedCornerShape(6.dp), - color = MaterialTheme.colorScheme.secondaryContainer, - ) { + if (scene.type == AutomationType.AUTOMATIC) { Text( - text = stringResource(R.string.scene_action_count, scene.actions.size), - modifier = Modifier.padding(horizontal = 6.dp, vertical = 2.dp), - style = MaterialTheme.typography.labelSmall, - color = MaterialTheme.colorScheme.onSecondaryContainer, + text = if (scene.triggers.isNotEmpty()) "⚡ ${scene.triggers.size} 个触发器 • ${scene.actions.size} 个动作" else "${scene.actions.size} 个动作", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + } else { + Text( + text = "${scene.actions.size} 个执行动作", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, ) } } @@ -326,8 +322,9 @@ private fun SceneCard( if (scene.type == AutomationType.MANUAL) { FilledTonalButton( onClick = onQuickExecute, - contentPadding = PaddingValues(horizontal = 10.dp, vertical = 4.dp), + contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp), modifier = Modifier.height(32.dp), + shape = RoundedCornerShape(8.dp), ) { Icon(Icons.Filled.PlayArrow, contentDescription = null, modifier = Modifier.size(16.dp)) Spacer(Modifier.width(4.dp)) @@ -336,10 +333,10 @@ private fun SceneCard( Spacer(Modifier.width(4.dp)) } IconButton(onClick = onEdit, modifier = Modifier.size(32.dp)) { - Icon(Icons.Filled.Edit, contentDescription = stringResource(R.string.scene_edit), modifier = Modifier.size(18.dp)) + Icon(Icons.Filled.Edit, contentDescription = stringResource(R.string.scene_edit), modifier = Modifier.size(18.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant) } IconButton(onClick = onDelete, modifier = Modifier.size(32.dp)) { - Icon(Icons.Filled.Delete, contentDescription = stringResource(R.string.scene_delete), modifier = Modifier.size(18.dp)) + Icon(Icons.Filled.Delete, contentDescription = stringResource(R.string.scene_delete), modifier = Modifier.size(18.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant) } } } @@ -349,27 +346,20 @@ private fun SceneCard( @Composable private fun TypeBadge(type: AutomationType) { - val (label, bg, fg) = when (type) { - AutomationType.MANUAL -> Triple( - stringResource(R.string.scene_tab_manual), - MaterialTheme.colorScheme.primaryContainer, - MaterialTheme.colorScheme.onPrimaryContainer, - ) - AutomationType.AUTOMATIC -> Triple( - stringResource(R.string.scene_tab_automatic), - MaterialTheme.colorScheme.secondaryContainer, - MaterialTheme.colorScheme.onSecondaryContainer, - ) + val label = when (type) { + AutomationType.MANUAL -> stringResource(R.string.scene_tab_manual) + AutomationType.AUTOMATIC -> stringResource(R.string.scene_tab_automatic) } Surface( shape = RoundedCornerShape(4.dp), - color = bg, + color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f), + border = BorderStroke(0.5.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.4f)), ) { Text( text = label, - modifier = Modifier.padding(horizontal = 4.dp, vertical = 1.dp), + modifier = Modifier.padding(horizontal = 5.dp, vertical = 1.dp), style = MaterialTheme.typography.labelSmall, - color = fg, + color = MaterialTheme.colorScheme.onSurfaceVariant, ) } } @@ -377,9 +367,7 @@ private fun TypeBadge(type: AutomationType) { @Composable private fun EmptySceneList(modifier: Modifier = Modifier) { Column( - modifier = modifier - .fillMaxSize() - .padding(32.dp), + modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { @@ -423,5 +411,3 @@ internal fun SceneColor.toColorOrNull(): Color? { val cleanHex = hex.removePrefix("#") return runCatching { Color(cleanHex.toLong(16) or 0xFF000000.toInt().toLong()) }.getOrNull() } - -