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. 383
      shared/src/commonMain/kotlin/com/whitefish/ring/ui/home/setting/SettingScreen.kt
  3. 135
      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

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

@ -1,22 +1,44 @@
package com.whitefish.ring.ui.home.setting
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
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.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.material3.Card
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.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
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 androidx.lifecycle.viewmodel.compose.viewModel
import org.jetbrains.compose.resources.painterResource
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
fun SettingScreen(
@ -25,93 +47,356 @@ fun SettingScreen(
) {
val uiState by viewModel.uiState.collectAsState()
Box(
modifier = modifier.fillMaxSize()
) {
LazyColumn(
modifier = modifier
modifier = Modifier
.fillMaxSize()
.background(Color(0xFF1A1A1A))
.padding(horizontal = 16.dp),
contentPadding = PaddingValues(vertical = 16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(uiState.settingItems) { setting ->
SettingItem(
setting = setting,
onItemClick = { viewModel.onSettingClick(setting) }
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 SettingItem(
setting: SettingItemData,
onItemClick: () -> Unit,
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
) {
// 戒指图像占位符
Box(
modifier = Modifier
.size(160.dp)
.clip(CircleShape),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(Res.drawable.ic_ring),
contentDescription = null,
modifier = Modifier.fillMaxSize()
)
}
}
}
@Composable
private fun ConnectionStatusSection(
isConnected: Boolean,
batteryLevel: Int,
modifier: Modifier = Modifier
) {
Card(
modifier = modifier
.fillMaxWidth()
.clickable { onItemClick() },
shape = RoundedCornerShape(12.dp),
modifier = modifier,
shape = RoundedCornerShape(15.dp),
colors = CardDefaults.cardColors(
containerColor = Color(0xFF2A2A2A)
containerColor = Color.White.copy(alpha = 0.9f)
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.fillMaxSize()
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
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 = "$batteryLevel%",
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = Color.Black
)
}
}
}
}
@Composable
private fun FeatureGridSection(
features: List<FeatureItemData>,
onFeatureClick: (FeatureItemData) -> Unit,
modifier: Modifier = Modifier
) {
// 将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))
}
}
}
}
}
@Composable
private fun FeatureCard(
feature: FeatureItemData,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
Card(
modifier = modifier
.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 = setting.title,
color = Color.White,
text = getFeatureIconText(feature.id),
fontSize = 16.sp,
fontWeight = FontWeight.Medium
color = Color.White,
fontWeight = FontWeight.Bold
)
}
}
Spacer(Modifier.width(22.dp))
if (setting.subtitle.isNotEmpty()) {
Spacer(modifier = Modifier.height(4.dp))
}
}
}
@Composable
private fun OtherSettingsSection(
settingItems: List<SettingItemData>,
onSettingClick: (SettingItemData) -> Unit,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = setting.subtitle,
color = Color.Gray,
fontSize = 14.sp
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)
)
}
}
}
}
if (setting.hasSwitch) {
Switch(
checked = setting.isEnabled,
onCheckedChange = { /* Handle switch change */ },
colors = SwitchDefaults.colors(
checkedThumbColor = Color.White,
checkedTrackColor = Color(0xFF352764),
uncheckedThumbColor = Color.Gray,
uncheckedTrackColor = Color.DarkGray
)
@Composable
private fun SettingItem(
setting: SettingItemData,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
Card(
modifier = modifier
.fillMaxWidth()
.clickable { onClick() },
shape = RoundedCornerShape(20.dp),
colors = CardDefaults.cardColors(
containerColor = Color(0xff352764)
)
} else {
) {
Row(
modifier = Modifier
.fillMaxSize()
.padding(start = 12.dp,end = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = ">",
color = Color.Gray,
fontSize = 18.sp
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)
// )
}
}
}
}
data class SettingItemData(
val title: String,
val subtitle: String = "",
val hasSwitch: Boolean = false,
val isEnabled: Boolean = false
)
// 辅助函数:获取功能图标颜色
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
@Composable

135
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.StateFlow
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(
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 isLoading: Boolean = false
)
@ -16,66 +41,84 @@ class SettingViewModel : ViewModel() {
val uiState: StateFlow<SettingUiState> = _uiState.asStateFlow()
init {
loadSettingItems()
loadData()
}
private fun loadSettingItems() {
// 模拟加载设置项数据
val mockData = listOf(
SettingItemData(
title = "设备连接",
subtitle = "管理蓝牙设备连接"
),
SettingItemData(
title = "数据同步",
subtitle = "自动同步健康数据",
hasSwitch = true,
isEnabled = true
),
SettingItemData(
title = "通知设置",
subtitle = "运动提醒和健康通知"
),
SettingItemData(
title = "隐私设置",
subtitle = "数据隐私和权限管理"
),
SettingItemData(
title = "夜间模式",
subtitle = "自动切换深色主题",
hasSwitch = true,
isEnabled = false
),
SettingItemData(
title = "关于应用",
subtitle = "版本信息和帮助"
),
SettingItemData(
title = "退出登录",
subtitle = ""
private fun loadData() {
// 功能模块数据
val featureItems = listOf(
FeatureItemData("smart_life", "智慧生活\n联动"),
FeatureItemData("wallet", "钱包"),
FeatureItemData("message_notification", "消息通知", hasNotification = true),
FeatureItemData("find_device", "找设备"),
FeatureItemData("alarm", "闹钟"),
FeatureItemData("message_reminder", "消息提醒"),
FeatureItemData("wechat", "微信绑定"),
FeatureItemData("manual", "产品手册")
)
// 设置项数据
val settingItems = listOf(
SettingItemData("设备设置"),
SettingItemData("恢复出厂设置"),
SettingItemData("固件更新"),
SettingItemData("帮助与客服"),
SettingItemData("设备信息")
)
_uiState.value = _uiState.value.copy(settingItems = mockData)
_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) {
// 处理设置项点击事件
when (setting.title) {
"设备连接" -> {
// 跳转到设备连接页面
"设备设置" -> {
// 跳转到设备设置页面
}
"通知设置" -> {
// 跳转到通知设置页面
"恢复出厂设置" -> {
// 显示恢复出厂设置确认对话框
}
"隐私设置" -> {
// 跳转到隐私设置页面
"固件更新" -> {
// 跳转到固件更新页面
}
"关于应用" -> {
// 跳转到关于页面
"帮助与客服" -> {
// 跳转到帮助与客服页面
}
"退出登录" -> {
// 处理退出登录
"设备信息" -> {
// 跳转到设备信息页面
}
}
}

Loading…
Cancel
Save