修复我的-顶部状态栏在完全变色后切换深色模式不会变色
调整选择星座界面ui以及添加缺省图
@@ -0,0 +1,15 @@
|
|||||||
|
package com.aiosman.ravenow.ui.account
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ZodiacBottomSheetHost() {
|
||||||
|
val show = ZodiacSheetManager.visible.collectAsState(false).value
|
||||||
|
if (show) {
|
||||||
|
ZodiacSelectBottomSheet(
|
||||||
|
onClose = { ZodiacSheetManager.close() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,39 +1,64 @@
|
|||||||
package com.aiosman.ravenow.ui.account
|
package com.aiosman.ravenow.ui.account
|
||||||
|
|
||||||
|
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.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.asPaddingValues
|
||||||
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.layout.systemBars
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
|
import androidx.compose.foundation.lazy.grid.itemsIndexed
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.rememberModalBottomSheetState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
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.draw.clip
|
||||||
|
import androidx.compose.ui.draw.shadow
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.input.nestedscroll.NestedScrollConnection
|
||||||
|
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||||
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.unit.Velocity
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
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.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.Check
|
|
||||||
import com.aiosman.ravenow.AppState
|
import com.aiosman.ravenow.AppState
|
||||||
import com.aiosman.ravenow.LocalAppTheme
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
import com.aiosman.ravenow.LocalNavController
|
|
||||||
import com.aiosman.ravenow.R
|
import com.aiosman.ravenow.R
|
||||||
import com.aiosman.ravenow.ui.comment.NoticeScreenHeader
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
|
|
||||||
// 星座资源ID列表
|
// 星座资源ID列表
|
||||||
val ZODIAC_SIGN_RES_IDS = listOf(
|
val ZODIAC_SIGN_RES_IDS = listOf(
|
||||||
@@ -51,6 +76,27 @@ val ZODIAC_SIGN_RES_IDS = listOf(
|
|||||||
R.string.zodiac_pisces
|
R.string.zodiac_pisces
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据星座资源ID获取对应的图片资源ID
|
||||||
|
*/
|
||||||
|
fun getZodiacImageResId(zodiacResId: Int): Int {
|
||||||
|
return when (zodiacResId) {
|
||||||
|
R.string.zodiac_aries -> R.mipmap.baiyang
|
||||||
|
R.string.zodiac_taurus -> R.mipmap.jingniu
|
||||||
|
R.string.zodiac_gemini -> R.mipmap.shuangzi
|
||||||
|
R.string.zodiac_cancer -> R.mipmap.juxie
|
||||||
|
R.string.zodiac_leo -> R.mipmap.shizi
|
||||||
|
R.string.zodiac_virgo -> R.mipmap.chunv
|
||||||
|
R.string.zodiac_libra -> R.mipmap.tiancheng
|
||||||
|
R.string.zodiac_scorpio -> R.mipmap.tianxie
|
||||||
|
R.string.zodiac_sagittarius -> R.mipmap.sheshou
|
||||||
|
R.string.zodiac_capricorn -> R.mipmap.moxie
|
||||||
|
R.string.zodiac_aquarius -> R.mipmap.shuiping
|
||||||
|
R.string.zodiac_pisces -> R.mipmap.shuangyu
|
||||||
|
else -> R.mipmap.xingzuo // 默认使用占位图片
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据存储的星座字符串(可能是任何语言)找到对应的资源ID
|
* 根据存储的星座字符串(可能是任何语言)找到对应的资源ID
|
||||||
* 如果找不到,返回null
|
* 如果找不到,返回null
|
||||||
@@ -72,37 +118,173 @@ fun findZodiacResId(storedZodiac: String?): Int? {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ZodiacSelectScreen() {
|
fun ZodiacSelectBottomSheet(
|
||||||
val navController = LocalNavController.current
|
onClose: () -> Unit
|
||||||
|
) {
|
||||||
val appColors = LocalAppTheme.current
|
val appColors = LocalAppTheme.current
|
||||||
|
val isDarkMode = AppState.darkMode
|
||||||
val model = AccountEditViewModel
|
val model = AccountEditViewModel
|
||||||
val currentZodiacResId = findZodiacResId(model.zodiac)
|
val currentZodiacResId = findZodiacResId(model.zodiac)
|
||||||
|
val sheetBackgroundColor = if (isDarkMode) {
|
||||||
|
appColors.secondaryBackground
|
||||||
|
} else {
|
||||||
|
Color(0xFFFFFFFF)
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
// 确保弹窗展开
|
||||||
.background(appColors.profileBackground)
|
LaunchedEffect(Unit) {
|
||||||
|
sheetState.expand()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听状态变化,确保弹窗始终展开(防止拖拽关闭和滑动)
|
||||||
|
LaunchedEffect(sheetState.currentValue, sheetState.targetValue, sheetState.isVisible) {
|
||||||
|
// 如果弹窗被拖拽关闭或位置发生变化,立即重新展开
|
||||||
|
if (!sheetState.isVisible || sheetState.targetValue != androidx.compose.material3.SheetValue.Expanded) {
|
||||||
|
kotlinx.coroutines.delay(10) // 短暂延迟确保状态更新
|
||||||
|
sheetState.expand()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val statusBarPadding = WindowInsets.systemBars.asPaddingValues()
|
||||||
|
val configuration = LocalConfiguration.current
|
||||||
|
val screenHeight = configuration.screenHeightDp.dp
|
||||||
|
val offsetY = screenHeight * 0.07f - statusBarPadding.calculateTopPadding()
|
||||||
|
|
||||||
|
ModalBottomSheet(
|
||||||
|
onDismissRequest = onClose,
|
||||||
|
sheetState = sheetState,
|
||||||
|
containerColor = sheetBackgroundColor, // 根据主题自适应背景
|
||||||
|
dragHandle = null
|
||||||
) {
|
) {
|
||||||
// 头部
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 16.dp)
|
.fillMaxHeight(0.95f)
|
||||||
|
.offset(y = offsetY)
|
||||||
|
.padding(
|
||||||
|
start = 16.dp,
|
||||||
|
end = 16.dp,
|
||||||
|
bottom = 8.dp
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
NoticeScreenHeader(
|
Column(
|
||||||
title = stringResource(R.string.choose_zodiac),
|
modifier = Modifier
|
||||||
moreIcon = false
|
.fillMaxWidth()
|
||||||
|
.fillMaxHeight()
|
||||||
|
) {
|
||||||
|
// 头部 - 使用 Box 实现绝对居中布局
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(48.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
val cancelButtonGradientColors = if (isDarkMode) {
|
||||||
|
listOf(
|
||||||
|
Color(0xFF3A3A3C),
|
||||||
|
Color(0xFF2C2C2E)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
listOf(
|
||||||
|
Color(0xFFFFFFFF),
|
||||||
|
Color(0xFFF8F8F8)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val cancelButtonContentColor = if (isDarkMode) Color(0xFFFFFFFF) else Color(0xFF404040)
|
||||||
|
|
||||||
|
// 左上角返回按钮 - 根据 Swift 代码样式,带淡灰色渐变背景
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterStart)
|
||||||
|
.height(36.dp)
|
||||||
|
.clip(RoundedCornerShape(18.dp)) // 圆角 100.0 在 36dp 高度下接近完全圆角
|
||||||
|
.background(
|
||||||
|
brush = Brush.linearGradient(
|
||||||
|
colors = cancelButtonGradientColors
|
||||||
|
// 不指定 start 和 end,默认从左上到右下
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.noRippleClickable { onClose() }
|
||||||
|
.padding(horizontal = 8.dp), // 内部 padding 确保内容不贴边
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
// 左箭头图标
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.drawable.rider_pro_back_icon),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(17.dp),
|
||||||
|
colorFilter = ColorFilter.tint(cancelButtonContentColor)
|
||||||
|
)
|
||||||
|
|
||||||
|
// "取消" 文字
|
||||||
|
Text(
|
||||||
|
text = "取消",
|
||||||
|
fontSize = 17.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = cancelButtonContentColor,
|
||||||
|
textAlign = androidx.compose.ui.text.style.TextAlign.Center
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 列表
|
// 中间标题 - 绝对居中
|
||||||
LazyColumn(
|
Text(
|
||||||
modifier = Modifier.fillMaxSize(),
|
text = stringResource(R.string.choose_zodiac),
|
||||||
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 16.dp, vertical = 8.dp)
|
color = appColors.text,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
textAlign = androidx.compose.ui.text.style.TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(Modifier.height(12.dp))
|
||||||
|
|
||||||
|
// 创建 NestedScrollConnection 来阻止滚动事件向上传播到 ModalBottomSheet
|
||||||
|
val nestedScrollConnection = remember {
|
||||||
|
object : NestedScrollConnection {
|
||||||
|
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
||||||
|
// 不消费任何事件,让 LazyVerticalGrid 先处理
|
||||||
|
return Offset.Zero
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
|
||||||
|
// 消费 LazyVerticalGrid 处理后的剩余滚动事件,防止传递到 ModalBottomSheet
|
||||||
|
return available
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun onPreFling(available: Velocity): Velocity {
|
||||||
|
// 不消费惯性滚动,让 LazyVerticalGrid 先处理
|
||||||
|
return Velocity.Zero
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
|
||||||
|
// 消费 LazyVerticalGrid 处理后的剩余惯性滚动,防止传递到 ModalBottomSheet
|
||||||
|
return available
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网格列表 - 2列
|
||||||
|
LazyVerticalGrid(
|
||||||
|
columns = GridCells.Fixed(2),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f)
|
||||||
|
.nestedScroll(nestedScrollConnection),
|
||||||
|
contentPadding = PaddingValues(
|
||||||
|
start = 8.dp,
|
||||||
|
top = 8.dp,
|
||||||
|
end = 8.dp,
|
||||||
|
bottom = 8.dp
|
||||||
|
),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||||
) {
|
) {
|
||||||
items(ZODIAC_SIGN_RES_IDS.size) { index ->
|
itemsIndexed(ZODIAC_SIGN_RES_IDS) { index, zodiacResId ->
|
||||||
val zodiacResId = ZODIAC_SIGN_RES_IDS[index]
|
|
||||||
val zodiacText = stringResource(zodiacResId)
|
val zodiacText = stringResource(zodiacResId)
|
||||||
ZodiacItem(
|
ZodiacItem(
|
||||||
zodiac = zodiacText,
|
zodiac = zodiacText,
|
||||||
@@ -115,13 +297,26 @@ fun ZodiacSelectScreen() {
|
|||||||
AppState.UserId?.let { uid ->
|
AppState.UserId?.let { uid ->
|
||||||
com.aiosman.ravenow.AppStore.setUserZodiac(uid, zodiacText)
|
com.aiosman.ravenow.AppStore.setUserZodiac(uid, zodiacText)
|
||||||
}
|
}
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保留原有的 ZodiacSelectScreen 用于导航路由(如果需要)
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun ZodiacSelectScreen() {
|
||||||
|
val navController = com.aiosman.ravenow.LocalNavController.current
|
||||||
|
ZodiacSelectBottomSheet(
|
||||||
|
onClose = {
|
||||||
navController.navigateUp()
|
navController.navigateUp()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -132,41 +327,58 @@ fun ZodiacItem(
|
|||||||
onClick: () -> Unit
|
onClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
val appColors = LocalAppTheme.current
|
val appColors = LocalAppTheme.current
|
||||||
|
val isDarkMode = AppState.darkMode
|
||||||
|
|
||||||
Box(
|
// 卡片背景色:浅灰色 (250, 249, 251)
|
||||||
|
// 暗色模式下使用比背景色更亮的颜色,以形成对比
|
||||||
|
val cardBackgroundColor = if (isDarkMode) {
|
||||||
|
Color(0xFF2A2A2A) // 比 secondaryBackground (0xFF1C1C1C) 更亮的灰色
|
||||||
|
} else {
|
||||||
|
Color(0xFFFAF9FB)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(16.dp))
|
.aspectRatio(1.1f) // 增加宽高比,使高度相对更低
|
||||||
.background(if (isSelected) appColors.main.copy(alpha = 0.1f) else Color.White)
|
.shadow(
|
||||||
|
elevation = if (isDarkMode) 8.dp else 2.dp, // 深色模式下更强的阴影
|
||||||
|
shape = RoundedCornerShape(21.dp),
|
||||||
|
spotColor = if (isDarkMode) Color.Black.copy(alpha = 0.5f) else Color.Black.copy(alpha = 0.1f)
|
||||||
|
)
|
||||||
|
.clip(RoundedCornerShape(21.dp))
|
||||||
|
.background(cardBackgroundColor)
|
||||||
.clickable(
|
.clickable(
|
||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() }
|
interactionSource = remember { MutableInteractionSource() }
|
||||||
) {
|
) {
|
||||||
onClick()
|
onClick()
|
||||||
}
|
}
|
||||||
.padding(16.dp)
|
.padding(horizontal = 24.dp, vertical = 12.dp), // 减小垂直padding,确保文本不被遮挡
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
Row(
|
// 星座图标 - 使用对应星座的图片
|
||||||
modifier = Modifier.fillMaxWidth(),
|
Box(
|
||||||
verticalAlignment = Alignment.CenterVertically
|
modifier = Modifier.size(100.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = getZodiacImageResId(zodiacResId)),
|
||||||
|
contentDescription = zodiac,
|
||||||
|
modifier = Modifier.size(100.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 星座名称 - 使用负间距让文本向上移动,与图标更靠近
|
||||||
Text(
|
Text(
|
||||||
text = zodiac,
|
text = zodiac,
|
||||||
fontSize = 17.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Medium,
|
||||||
color = if (isSelected) appColors.main else appColors.text,
|
color = appColors.text,
|
||||||
modifier = Modifier.weight(1f)
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.offset(y = (-20).dp) // 负间距,让文本进一步向上移动
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isSelected) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.Check,
|
|
||||||
contentDescription = "Selected",
|
|
||||||
modifier = Modifier.size(20.dp),
|
|
||||||
tint = appColors.main
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.aiosman.ravenow.ui.account
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
|
||||||
|
object ZodiacSheetManager {
|
||||||
|
private val _visible = MutableStateFlow(false)
|
||||||
|
val visible: StateFlow<Boolean> = _visible.asStateFlow()
|
||||||
|
|
||||||
|
fun open() {
|
||||||
|
_visible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun close() {
|
||||||
|
_visible.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -75,6 +75,8 @@ import com.aiosman.ravenow.ui.composables.pickupAndCompressLauncher
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
|
import com.aiosman.ravenow.ui.account.ZodiacBottomSheetHost
|
||||||
|
import com.aiosman.ravenow.ui.account.ZodiacSheetManager
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编辑用户资料界面
|
* 编辑用户资料界面
|
||||||
@@ -190,6 +192,9 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
|
|||||||
darkIcons = !AppState.darkMode, // 根据暗色模式决定图标颜色
|
darkIcons = !AppState.darkMode, // 根据暗色模式决定图标颜色
|
||||||
maskBoxBackgroundColor = Color.Transparent
|
maskBoxBackgroundColor = Color.Transparent
|
||||||
) {
|
) {
|
||||||
|
// 挂载星座选择弹窗
|
||||||
|
ZodiacBottomSheetHost()
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@@ -448,9 +453,7 @@ fun AccountEditScreen2(onUpdateBanner: ((Uri, File, Context) -> Unit)? = null,)
|
|||||||
iconResDark = R.mipmap.frame_4, // 星座暗色模式图标
|
iconResDark = R.mipmap.frame_4, // 星座暗色模式图标
|
||||||
iconResLight = R.mipmap.xingzuo, // 星座亮色模式图标
|
iconResLight = R.mipmap.xingzuo, // 星座亮色模式图标
|
||||||
onClick = {
|
onClick = {
|
||||||
debouncedNavigation {
|
ZodiacSheetManager.open()
|
||||||
navController.navigate(NavigationRoute.ZodiacSelect.route)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -683,19 +683,27 @@ fun TopNavigationBar(
|
|||||||
// 仅本人主页显示积分:收集全局积分
|
// 仅本人主页显示积分:收集全局积分
|
||||||
val pointsBalanceState = if (isSelf) PointService.pointsBalance.collectAsState(initial = null) else null
|
val pointsBalanceState = if (isSelf) PointService.pointsBalance.collectAsState(initial = null) else null
|
||||||
|
|
||||||
|
// 响应式监听暗色模式变化 - 通过 LocalAppTheme 的变化来触发重组
|
||||||
|
// 当 AppState.darkMode 改变时,AppState.appTheme 也会改变,从而触发 LocalAppTheme 更新
|
||||||
|
val darkMode = AppState.darkMode
|
||||||
|
|
||||||
// 根据背景透明度和暗色模式决定图标颜色
|
// 根据背景透明度和暗色模式决定图标颜色
|
||||||
// 暗色模式下:图标始终为白色
|
// 暗色模式下:图标始终为白色
|
||||||
// 亮色模式下:根据背景透明度决定,透明度为1时变黑,否则为白色
|
// 亮色模式下:根据背景透明度决定,透明度为1时变黑,否则为白色
|
||||||
val iconColor = if (AppState.darkMode) {
|
val iconColor = remember(darkMode, backgroundAlpha) {
|
||||||
|
if (darkMode) {
|
||||||
Color.White // 暗色模式下图标始终为白色
|
Color.White // 暗色模式下图标始终为白色
|
||||||
} else {
|
} else {
|
||||||
if (backgroundAlpha >= 1f) Color.Black else Color.White
|
if (backgroundAlpha >= 1f) Color.Black else Color.White
|
||||||
}
|
}
|
||||||
val cardBorderColor = if (AppState.darkMode) {
|
}
|
||||||
|
val cardBorderColor = remember(darkMode, backgroundAlpha) {
|
||||||
|
if (darkMode) {
|
||||||
Color.White.copy(alpha = 0.35f) // 暗色模式下使用半透明白色,避免整体变白
|
Color.White.copy(alpha = 0.35f) // 暗色模式下使用半透明白色,避免整体变白
|
||||||
} else {
|
} else {
|
||||||
if (backgroundAlpha >= 1f) Color.Black else Color.White
|
if (backgroundAlpha >= 1f) Color.Black else Color.White
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -709,10 +717,10 @@ fun TopNavigationBar(
|
|||||||
val totalHeight = statusBarHeight + navigationBarHeight
|
val totalHeight = statusBarHeight + navigationBarHeight
|
||||||
|
|
||||||
// 根据滚动位置计算背景颜色,从透明逐渐变为实色填充,尽快完成
|
// 根据滚动位置计算背景颜色,从透明逐渐变为实色填充,尽快完成
|
||||||
val toolbarBackgroundColor = remember(backgroundAlpha) {
|
val toolbarBackgroundColor = remember(backgroundAlpha, darkMode) {
|
||||||
val progress = backgroundAlpha.coerceIn(0f, 1f)
|
val progress = backgroundAlpha.coerceIn(0f, 1f)
|
||||||
|
|
||||||
if (AppState.darkMode) {
|
if (darkMode) {
|
||||||
// 暗色模式下:从透明逐渐变为黑色实色填充
|
// 暗色模式下:从透明逐渐变为黑色实色填充
|
||||||
Color.Black.copy(alpha = progress)
|
Color.Black.copy(alpha = progress)
|
||||||
} else {
|
} else {
|
||||||
@@ -744,9 +752,9 @@ fun TopNavigationBar(
|
|||||||
// 左侧:互动数据卡片(仅自己的界面显示)
|
// 左侧:互动数据卡片(仅自己的界面显示)
|
||||||
if (isSelf) {
|
if (isSelf) {
|
||||||
// 根据 toolbar 背景透明度动态调整卡片背景
|
// 根据 toolbar 背景透明度动态调整卡片背景
|
||||||
val cardBackgroundColor = remember(backgroundAlpha) {
|
val cardBackgroundColor = remember(backgroundAlpha, darkMode) {
|
||||||
val smoothProgress = backgroundAlpha.coerceIn(0f, 1f)
|
val smoothProgress = backgroundAlpha.coerceIn(0f, 1f)
|
||||||
if (AppState.darkMode) {
|
if (darkMode) {
|
||||||
// 暗色模式:保持在半透明灰白区间,避免滚动到顶部后变纯白
|
// 暗色模式:保持在半透明灰白区间,避免滚动到顶部后变纯白
|
||||||
val minAlpha = 0.18f
|
val minAlpha = 0.18f
|
||||||
val maxAlpha = 0.35f
|
val maxAlpha = 0.35f
|
||||||
@@ -786,7 +794,7 @@ fun TopNavigationBar(
|
|||||||
text = pointsBalanceState?.value?.balance?.let { numberFormat.format(it) } ?: "--",
|
text = pointsBalanceState?.value?.balance?.let { numberFormat.format(it) } ?: "--",
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
fontWeight = FontWeight.W500,
|
fontWeight = FontWeight.W500,
|
||||||
color = if (AppState.darkMode) Color.White else Color.Black, // 暗色模式下为白色,亮色模式下为黑色
|
color = remember(darkMode) { if (darkMode) Color.White else Color.Black }, // 暗色模式下为白色,亮色模式下为黑色
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -839,7 +847,7 @@ fun TopNavigationBar(
|
|||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
// 返回按钮:深色模式下为白色,亮色模式下为黑色
|
// 返回按钮:深色模式下为白色,亮色模式下为黑色
|
||||||
val backButtonColor = if (AppState.darkMode) Color.White else Color.Black
|
val backButtonColor = remember(darkMode) { if (darkMode) Color.White else Color.Black }
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_back_icon),
|
painter = painterResource(id = R.drawable.rider_pro_back_icon),
|
||||||
contentDescription = "Back",
|
contentDescription = "Back",
|
||||||
|
|||||||
BIN
app/src/main/res/mipmap-hdpi/baiyang.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/mipmap-hdpi/chunv.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/jingniu.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
app/src/main/res/mipmap-hdpi/juxie.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/moxie.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/sheshou.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-hdpi/shizi.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
app/src/main/res/mipmap-hdpi/shuangyu.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-hdpi/shuangzi.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/mipmap-hdpi/shuiping.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/mipmap-hdpi/tiancheng.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/tianxie.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-mdpi/baiyang.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/mipmap-mdpi/chunv.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/jingniu.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/juxie.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/mipmap-mdpi/moxie.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/sheshou.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-mdpi/shizi.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/shuangyu.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-mdpi/shuangzi.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/shuiping.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/mipmap-mdpi/tiancheng.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/tianxie.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/mipmap-xhdpi/baiyang.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/chunv.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-xhdpi/jingniu.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/juxie.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-xhdpi/moxie.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/sheshou.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
app/src/main/res/mipmap-xhdpi/shizi.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-xhdpi/shuangyu.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-xhdpi/shuangzi.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/shuiping.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/tiancheng.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/mipmap-xhdpi/tianxie.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/baiyang.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/chunv.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/jingniu.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/juxie.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/moxie.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/sheshou.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/shizi.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/shuangyu.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/shuangzi.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/shuiping.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/tiancheng.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/tianxie.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/baiyang.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/chunv.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/jingniu.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/juxie.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/moxie.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/sheshou.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/shizi.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/shuangyu.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/shuangzi.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/shuiping.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/tiancheng.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/tianxie.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |