Browse Source

feat:setting ui

dev_ios
AnranYus 3 weeks ago
parent
commit
5793a36b17
  1. BIN
      shared/src/commonMain/composeResources/drawable/ic_ring.png
  2. 397
      shared/src/commonMain/kotlin/com/whitefish/ring/ui/home/setting/SettingScreen.kt
  3. 137
      shared/src/commonMain/kotlin/com/whitefish/ring/ui/home/setting/SettingViewModel.kt

BIN
shared/src/commonMain/composeResources/drawable/ic_ring.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

397
shared/src/commonMain/kotlin/com/whitefish/ring/ui/home/setting/SettingScreen.kt

@ -1,22 +1,44 @@
package com.whitefish.ring.ui.home.setting package com.whitefish.ring.ui.home.setting
import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.* import androidx.compose.material3.Card
import androidx.compose.runtime.* import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight 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.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.compose.ui.tooling.preview.Preview
import kotlin.invoke import ring.shared.generated.resources.Res
import ring.shared.generated.resources.ic_ring
@Composable @Composable
fun SettingScreen( fun SettingScreen(
@ -25,93 +47,356 @@ fun SettingScreen(
) { ) {
val uiState by viewModel.uiState.collectAsState() val uiState by viewModel.uiState.collectAsState()
LazyColumn( Box(
modifier = modifier modifier = modifier.fillMaxSize()
.fillMaxSize() ) {
.background(Color(0xFF1A1A1A)) LazyColumn(
.padding(horizontal = 16.dp), modifier = Modifier
contentPadding = PaddingValues(vertical = 16.dp), .fillMaxSize()
verticalArrangement = Arrangement.spacedBy(8.dp) .padding(horizontal = 16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
item {
Spacer(modifier = Modifier.height(40.dp))
}
// 顶部标题和头像
item {
TopSection(
deviceName = uiState.deviceName,
modifier = Modifier.fillMaxWidth()
)
}
// 戒指图像
item {
RingImageSection(
modifier = Modifier.fillMaxWidth()
)
}
// 连接状态和电池
item {
ConnectionStatusSection(
isConnected = uiState.isConnected,
batteryLevel = uiState.batteryLevel,
modifier = Modifier.fillMaxWidth().height(102.dp)
)
}
// 功能网格 - 使用分块显示而不是嵌套LazyGrid
item {
FeatureGridSection(
features = uiState.featureItems,
onFeatureClick = viewModel::onFeatureClick,
modifier = Modifier.fillMaxWidth()
)
}
// 其他设置
item {
OtherSettingsSection(
settingItems = uiState.settingItems,
onSettingClick = viewModel::onSettingClick,
modifier = Modifier.fillMaxWidth()
)
}
}
}
}
@Composable
private fun TopSection(
deviceName: String,
modifier: Modifier = Modifier
) {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = deviceName,
fontSize = 20.sp,
fontWeight = FontWeight.Medium,
color = Color.White
)
// 头像占位符
Box(
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.background(Color.White.copy(alpha = 0.3f)),
contentAlignment = Alignment.Center
) {
// Icon(
// imageVector = Icons.Default.Person,
// contentDescription = "用户头像",
// tint = Color.White,
// modifier = Modifier.size(24.dp)
// )
}
}
}
@Composable
private fun RingImageSection(
modifier: Modifier = Modifier
) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center
) { ) {
items(uiState.settingItems) { setting -> // 戒指图像占位符
SettingItem( Box(
setting = setting, modifier = Modifier
onItemClick = { viewModel.onSettingClick(setting) } .size(160.dp)
.clip(CircleShape),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(Res.drawable.ic_ring),
contentDescription = null,
modifier = Modifier.fillMaxSize()
) )
} }
} }
} }
@Composable @Composable
private fun SettingItem( private fun ConnectionStatusSection(
setting: SettingItemData, isConnected: Boolean,
onItemClick: () -> Unit, batteryLevel: Int,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
Card( Card(
modifier = modifier modifier = modifier,
.fillMaxWidth() shape = RoundedCornerShape(15.dp),
.clickable { onItemClick() },
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors( colors = CardDefaults.cardColors(
containerColor = Color(0xFF2A2A2A) containerColor = Color.White.copy(alpha = 0.9f)
) )
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxSize()
.padding(16.dp), .padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Column( Text(
modifier = Modifier.weight(1f) text = if (isConnected) "已连接" else "未连接",
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = Color.Black
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
// 电池图标占位符
Box(
modifier = Modifier
.size(20.dp, 12.dp)
.background(
color = if (batteryLevel > 20) Color.Green else Color.Red,
shape = RoundedCornerShape(2.dp)
)
)
Text( Text(
text = setting.title, text = "$batteryLevel%",
color = Color.White,
fontSize = 16.sp, fontSize = 16.sp,
fontWeight = FontWeight.Medium fontWeight = FontWeight.Medium,
color = Color.Black
) )
}
}
}
}
if (setting.subtitle.isNotEmpty()) { @Composable
Spacer(modifier = Modifier.height(4.dp)) private fun FeatureGridSection(
Text( features: List<FeatureItemData>,
text = setting.subtitle, onFeatureClick: (FeatureItemData) -> Unit,
color = Color.Gray, modifier: Modifier = Modifier
fontSize = 14.sp ) {
// 将features按每行2个分组
val chunkedFeatures = features.chunked(2)
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
chunkedFeatures.forEach { rowFeatures ->
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
rowFeatures.forEach { feature ->
FeatureCard(
feature = feature,
onClick = { onFeatureClick(feature) },
modifier = Modifier.weight(1f)
) )
} }
// 如果行中只有一个元素,添加一个空的spacer保持布局对称
if (rowFeatures.size == 1) {
Spacer(modifier = Modifier.weight(1f))
}
} }
}
}
}
if (setting.hasSwitch) { @Composable
Switch( private fun FeatureCard(
checked = setting.isEnabled, feature: FeatureItemData,
onCheckedChange = { /* Handle switch change */ }, onClick: () -> Unit,
colors = SwitchDefaults.colors( modifier: Modifier = Modifier
checkedThumbColor = Color.White, ) {
checkedTrackColor = Color(0xFF352764), Card(
uncheckedThumbColor = Color.Gray, modifier = modifier
uncheckedTrackColor = Color.DarkGray .height(85.dp)
.clickable { onClick() },
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(
containerColor = Color.White.copy(alpha = 0.9f)
)
) {
Row(modifier = Modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically) {
Spacer(Modifier.width(12.dp))
Column {
Text("Title", fontSize = 18.sp, color = Color(0xff394298))
Text("Subtitle", fontSize = 11.sp, color = Color(0xff978CB9))
}
Spacer(modifier = Modifier.weight(1f))
Column {
// 功能图标占位符
Box(
modifier = Modifier
.size(32.dp)
.clip(CircleShape)
.background(getFeatureIconColor(feature.id)),
contentAlignment = Alignment.Center
) {
Text(
text = getFeatureIconText(feature.id),
fontSize = 16.sp,
color = Color.White,
fontWeight = FontWeight.Bold
) )
}
}
Spacer(Modifier.width(22.dp))
}
}
}
@Composable
private fun OtherSettingsSection(
settingItems: List<SettingItemData>,
onSettingClick: (SettingItemData) -> Unit,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = "其他",
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = Color.White,
modifier = Modifier.padding(horizontal = 4.dp)
)
Column(
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
settingItems.forEach { setting ->
SettingItem(
setting = setting,
onClick = { onSettingClick(setting) },
modifier = Modifier.height(65.dp)
) )
} else {
Text(
text = ">",
color = Color.Gray,
fontSize = 18.sp
)
} }
} }
} }
} }
data class SettingItemData( @Composable
val title: String, private fun SettingItem(
val subtitle: String = "", setting: SettingItemData,
val hasSwitch: Boolean = false, onClick: () -> Unit,
val isEnabled: Boolean = false modifier: Modifier = Modifier
) ) {
Card(
modifier = modifier
.fillMaxWidth()
.clickable { onClick() },
shape = RoundedCornerShape(20.dp),
colors = CardDefaults.cardColors(
containerColor = Color(0xff352764)
)
) {
Row(
modifier = Modifier
.fillMaxSize()
.padding(start = 12.dp,end = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = setting.title,
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = Color.White
)
if (setting.hasArrow) {
// Icon(
// imageVector = Icons.Default.ArrowForwardIos,
// contentDescription = "前往",
// tint = Color.White,
// modifier = Modifier.size(16.dp)
// )
}
}
}
}
// 辅助函数:获取功能图标颜色
private fun getFeatureIconColor(featureId: String): Color {
return when (featureId) {
"smart_life" -> Color(0xFF4CAF50)
"wallet" -> Color(0xFFFF5722)
"message_notification" -> Color(0xFFFFC107)
"find_device" -> Color(0xFF2196F3)
"alarm" -> Color(0xFFFF9800)
"message_reminder" -> Color(0xFF9C27B0)
"wechat" -> Color(0xFF4CAF50)
"manual" -> Color(0xFF795548)
else -> Color.Gray
}
}
// 辅助函数:获取功能图标文本
private fun getFeatureIconText(featureId: String): String {
return when (featureId) {
"smart_life" -> "🏠"
"wallet" -> "💰"
"message_notification" -> "📧"
"find_device" -> "🔍"
"alarm" -> ""
"message_reminder" -> "💡"
"wechat" -> "💬"
"manual" -> "📖"
else -> "?"
}
}
@Preview @Preview
@Composable @Composable

137
shared/src/commonMain/kotlin/com/whitefish/ring/ui/home/setting/SettingViewModel.kt

@ -4,8 +4,33 @@ import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import org.jetbrains.compose.resources.DrawableResource
// 功能模块数据类
data class FeatureItemData(
val id: String,
val title: String,
val icon: DrawableResource? = null,
val isEnabled: Boolean = false,
val hasNotification: Boolean = false,
val onClick: (() -> Unit)? = null
)
// 设置项数据类
data class SettingItemData(
val title: String,
val subtitle: String = "",
val hasSwitch: Boolean = false,
val isEnabled: Boolean = false,
val hasArrow: Boolean = true,
val onClick: (() -> Unit)? = null
)
data class SettingUiState( data class SettingUiState(
val deviceName: String = "Star Ring Gen1",
val isConnected: Boolean = true,
val batteryLevel: Int = 100,
val featureItems: List<FeatureItemData> = emptyList(),
val settingItems: List<SettingItemData> = emptyList(), val settingItems: List<SettingItemData> = emptyList(),
val isLoading: Boolean = false val isLoading: Boolean = false
) )
@ -16,66 +41,84 @@ class SettingViewModel : ViewModel() {
val uiState: StateFlow<SettingUiState> = _uiState.asStateFlow() val uiState: StateFlow<SettingUiState> = _uiState.asStateFlow()
init { init {
loadSettingItems() loadData()
} }
private fun loadSettingItems() { private fun loadData() {
// 模拟加载设置项数据 // 功能模块数据
val mockData = listOf( val featureItems = listOf(
SettingItemData( FeatureItemData("smart_life", "智慧生活\n联动"),
title = "设备连接", FeatureItemData("wallet", "钱包"),
subtitle = "管理蓝牙设备连接" FeatureItemData("message_notification", "消息通知", hasNotification = true),
), FeatureItemData("find_device", "找设备"),
SettingItemData( FeatureItemData("alarm", "闹钟"),
title = "数据同步", FeatureItemData("message_reminder", "消息提醒"),
subtitle = "自动同步健康数据", FeatureItemData("wechat", "微信绑定"),
hasSwitch = true, FeatureItemData("manual", "产品手册")
isEnabled = true
),
SettingItemData(
title = "通知设置",
subtitle = "运动提醒和健康通知"
),
SettingItemData(
title = "隐私设置",
subtitle = "数据隐私和权限管理"
),
SettingItemData(
title = "夜间模式",
subtitle = "自动切换深色主题",
hasSwitch = true,
isEnabled = false
),
SettingItemData(
title = "关于应用",
subtitle = "版本信息和帮助"
),
SettingItemData(
title = "退出登录",
subtitle = ""
)
) )
_uiState.value = _uiState.value.copy(settingItems = mockData) // 设置项数据
val settingItems = listOf(
SettingItemData("设备设置"),
SettingItemData("恢复出厂设置"),
SettingItemData("固件更新"),
SettingItemData("帮助与客服"),
SettingItemData("设备信息")
)
_uiState.value = _uiState.value.copy(
featureItems = featureItems,
settingItems = settingItems
)
}
fun onFeatureClick(feature: FeatureItemData) {
// 处理功能项点击事件
when (feature.id) {
"smart_life" -> {
// 跳转到智慧生活联动页面
}
"wallet" -> {
// 跳转到钱包页面
}
"message_notification" -> {
// 跳转到消息通知设置页面
}
"find_device" -> {
// 执行查找设备功能
}
"alarm" -> {
// 跳转到闹钟设置页面
}
"message_reminder" -> {
// 跳转到消息提醒设置页面
}
"wechat" -> {
// 跳转到微信绑定页面
}
"manual" -> {
// 打开产品手册
}
}
} }
fun onSettingClick(setting: SettingItemData) { fun onSettingClick(setting: SettingItemData) {
// 处理设置项点击事件 // 处理设置项点击事件
when (setting.title) { when (setting.title) {
"设备连接" -> { "设备设置" -> {
// 跳转到设备连接页面 // 跳转到设备设置页面
} }
"通知设置" -> { "恢复出厂设置" -> {
// 跳转到通知设置页面 // 显示恢复出厂设置确认对话框
} }
"隐私设置" -> { "固件更新" -> {
// 跳转到隐私设置页面 // 跳转到固件更新页面
} }
"关于应用" -> { "帮助与客服" -> {
// 跳转到关于页面 // 跳转到帮助与客服页面
} }
"退出登录" -> { "设备信息" -> {
// 处理退出登录 // 跳转到设备信息页面
} }
} }
} }

Loading…
Cancel
Save