Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5878a1c1fa | |||
| f2330cc5fb | |||
| 76ce9685ac |
@@ -20,11 +20,13 @@ import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -47,6 +49,7 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.aiosman.ravenow.AppState
|
||||
@@ -107,48 +110,35 @@ fun MbtiSelectBottomSheet(
|
||||
|
||||
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
|
||||
// 确保弹窗展开
|
||||
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
|
||||
containerColor = Color.Transparent,
|
||||
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
||||
dragHandle = {}
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight(0.95f)
|
||||
.offset(y = offsetY)
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 8.dp
|
||||
)
|
||||
.fillMaxHeight()
|
||||
.padding(top = 8.dp)
|
||||
) {
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight()
|
||||
.clip(RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)),
|
||||
color = sheetBackgroundColor,
|
||||
tonalElevation = 0.dp,
|
||||
shadowElevation = 0.dp,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight()
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
) {
|
||||
// 头部 - 使用 Box 实现绝对居中布局
|
||||
// 头部
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -168,23 +158,27 @@ fun MbtiSelectBottomSheet(
|
||||
}
|
||||
val cancelButtonContentColor = if (isDarkMode) Color(0xFFFFFFFF) else Color(0xFF404040)
|
||||
|
||||
// 左上角返回按钮
|
||||
Row(
|
||||
// 左上角返回按钮:整体「箭头 + 取消」在按钮内居中
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.height(36.dp)
|
||||
.clip(RoundedCornerShape(18.dp))
|
||||
.width(91.dp)
|
||||
.height(44.dp)
|
||||
.clip(RoundedCornerShape(1000.dp))
|
||||
.background(
|
||||
brush = Brush.linearGradient(
|
||||
colors = cancelButtonGradientColors
|
||||
)
|
||||
)
|
||||
.noRippleClickable { onClose() }
|
||||
.padding(horizontal = 8.dp),
|
||||
.noRippleClickable { onClose() },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 12.dp, vertical = 4.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// 左箭头图标
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.rider_pro_back_icon),
|
||||
contentDescription = null,
|
||||
@@ -192,61 +186,64 @@ fun MbtiSelectBottomSheet(
|
||||
colorFilter = ColorFilter.tint(cancelButtonContentColor)
|
||||
)
|
||||
|
||||
// "取消" 文字
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
|
||||
Text(
|
||||
text = "取消",
|
||||
fontSize = 17.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = cancelButtonContentColor,
|
||||
textAlign = androidx.compose.ui.text.style.TextAlign.Center
|
||||
textAlign = TextAlign.Center,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Clip
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 中间标题 - 绝对居中
|
||||
// 中间标题
|
||||
Text(
|
||||
text = stringResource(R.string.choose_mbti),
|
||||
color = appColors.text,
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
textAlign = androidx.compose.ui.text.style.TextAlign.Center
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(12.dp))
|
||||
|
||||
// 创建 NestedScrollConnection 来阻止滚动事件向上传播到 ModalBottomSheet
|
||||
// NestedScroll,阻止滚动事件向上传到 BottomSheet
|
||||
val nestedScrollConnection = remember {
|
||||
object : NestedScrollConnection {
|
||||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
||||
// 不消费任何事件,让 LazyColumn 先处理
|
||||
return Offset.Zero
|
||||
}
|
||||
|
||||
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
|
||||
// 消费 LazyColumn 处理后的剩余滚动事件,防止传递到 ModalBottomSheet
|
||||
override fun onPostScroll(
|
||||
consumed: Offset,
|
||||
available: Offset,
|
||||
source: NestedScrollSource
|
||||
): Offset {
|
||||
return available
|
||||
}
|
||||
|
||||
override suspend fun onPreFling(available: Velocity): Velocity {
|
||||
// 不消费惯性滚动,让 LazyColumn 先处理
|
||||
return Velocity.Zero
|
||||
}
|
||||
|
||||
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
|
||||
// 消费 LazyColumn 处理后的剩余惯性滚动,防止传递到 ModalBottomSheet
|
||||
return available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MBTI解释文字背景色
|
||||
val descriptionBackgroundColor = if (isDarkMode) {
|
||||
Color(0xFF2A2A2A) // 比 secondaryBackground (0xFF1C1C1C) 更亮的灰色
|
||||
Color(0xFF2A2A2A)
|
||||
} else {
|
||||
Color(0xFFFAF9FB)
|
||||
}
|
||||
|
||||
// 使用LazyColumn包裹解释文字和MBTI类型网格,使它们一起滚动
|
||||
// 列表:上面是说明文字,下面是 MBTI 网格
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -260,7 +257,7 @@ fun MbtiSelectBottomSheet(
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
// MBTI解释文字 - 作为第一个item
|
||||
// 说明文字
|
||||
item {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
@@ -278,15 +275,17 @@ fun MbtiSelectBottomSheet(
|
||||
}
|
||||
}
|
||||
|
||||
// MBTI类型网格 - 手动创建2列网格布局
|
||||
// MBTI 类型网格(2 列)
|
||||
itemsIndexed(MBTI_TYPES.chunked(2)) { rowIndex, rowItems ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = if (rowIndex < MBTI_TYPES.chunked(2).size - 1) 10.dp else 0.dp),
|
||||
.padding(
|
||||
bottom = if (rowIndex < MBTI_TYPES.chunked(2).size - 1) 10.dp else 0.dp
|
||||
),
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp)
|
||||
) {
|
||||
rowItems.forEachIndexed { colIndex, mbti ->
|
||||
rowItems.forEach { mbti ->
|
||||
Box(
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
@@ -294,14 +293,13 @@ fun MbtiSelectBottomSheet(
|
||||
mbti = mbti,
|
||||
isSelected = mbti == currentMbti,
|
||||
onClick = {
|
||||
// 保存MBTI类型
|
||||
model.mbti = mbti
|
||||
onClose()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// 如果这一行只有1个item,添加一个空的Spacer来保持布局
|
||||
|
||||
if (rowItems.size == 1) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
@@ -312,6 +310,7 @@ fun MbtiSelectBottomSheet(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 保留原有的 MbtiSelectScreen 用于导航路由(如果需要)
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@@ -358,30 +357,26 @@ fun MbtiItem(
|
||||
) {
|
||||
onClick()
|
||||
}
|
||||
.padding(horizontal = 24.dp, vertical = 12.dp),
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
// MBTI图标 - 使用占位图片
|
||||
Box(
|
||||
modifier = Modifier.size(100.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
// 直接把 MBTI 图标和文字放在灰色卡片内部,布局与星座保持一致
|
||||
Image(
|
||||
painter = painterResource(id = getMbtiImageResId(mbti, isDarkMode)),
|
||||
contentDescription = mbti,
|
||||
modifier = Modifier.size(100.dp)
|
||||
modifier = Modifier.size(96.dp)
|
||||
)
|
||||
}
|
||||
|
||||
// MBTI名称 - 使用负间距让文本向上移动,与图标更靠近
|
||||
Spacer(modifier = Modifier.height(0.dp))
|
||||
|
||||
Text(
|
||||
text = mbti,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = appColors.text,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.offset(y = (-20).dp)
|
||||
modifier = Modifier.offset(y = (-10).dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -47,6 +48,7 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
@@ -135,48 +137,36 @@ fun ZodiacSelectBottomSheet(
|
||||
|
||||
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
|
||||
// 确保弹窗展开
|
||||
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
|
||||
// 对齐发布动态草稿箱样式:底层透明,内容区域自己绘制圆角和背景
|
||||
containerColor = Color.Transparent,
|
||||
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
||||
dragHandle = {}
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight(0.95f)
|
||||
.offset(y = offsetY)
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 8.dp
|
||||
)
|
||||
.fillMaxHeight()
|
||||
.padding(top = 8.dp)
|
||||
) {
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight()
|
||||
.clip(RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)),
|
||||
color = sheetBackgroundColor,
|
||||
tonalElevation = 0.dp,
|
||||
shadowElevation = 0.dp,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight()
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
) {
|
||||
// 头部 - 使用 Box 实现绝对居中布局
|
||||
// 头部 - 使用 Box 实现绝对居中布局(对齐草稿箱样式)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -196,24 +186,28 @@ fun ZodiacSelectBottomSheet(
|
||||
}
|
||||
val cancelButtonContentColor = if (isDarkMode) Color(0xFFFFFFFF) else Color(0xFF404040)
|
||||
|
||||
// 左上角返回按钮 - 根据 Swift 代码样式,带淡灰色渐变背景
|
||||
Row(
|
||||
// 左上角返回按钮:参考 iOS 设计,整体「箭头 + 取消」在 91x44 的按钮内居中
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.height(36.dp)
|
||||
.clip(RoundedCornerShape(18.dp)) // 圆角 100.0 在 36dp 高度下接近完全圆角
|
||||
.width(91.dp)
|
||||
.height(44.dp)
|
||||
.clip(RoundedCornerShape(1000.dp))
|
||||
.background(
|
||||
brush = Brush.linearGradient(
|
||||
colors = cancelButtonGradientColors
|
||||
// 不指定 start 和 end,默认从左上到右下
|
||||
)
|
||||
)
|
||||
.noRippleClickable { onClose() }
|
||||
.padding(horizontal = 8.dp), // 内部 padding 确保内容不贴边
|
||||
.noRippleClickable { onClose() },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
// 不再固定宽度,让内容自然占位,避免裁剪掉“消”字
|
||||
.padding(horizontal = 12.dp, vertical = 4.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// 左箭头图标
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.rider_pro_back_icon),
|
||||
contentDescription = null,
|
||||
@@ -221,17 +215,20 @@ fun ZodiacSelectBottomSheet(
|
||||
colorFilter = ColorFilter.tint(cancelButtonContentColor)
|
||||
)
|
||||
|
||||
// "取消" 文字
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
|
||||
Text(
|
||||
text = "取消",
|
||||
fontSize = 17.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = cancelButtonContentColor,
|
||||
textAlign = androidx.compose.ui.text.style.TextAlign.Center
|
||||
textAlign = androidx.compose.ui.text.style.TextAlign.Center,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Clip
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 中间标题 - 绝对居中
|
||||
Text(
|
||||
text = stringResource(R.string.choose_zodiac),
|
||||
color = appColors.text,
|
||||
@@ -243,32 +240,34 @@ fun ZodiacSelectBottomSheet(
|
||||
|
||||
Spacer(Modifier.height(12.dp))
|
||||
|
||||
// 创建 NestedScrollConnection 来阻止滚动事件向上传播到 ModalBottomSheet
|
||||
// 创建 NestedScrollConnection:
|
||||
// 1. 不抢在列表前面消费事件,让 LazyVerticalGrid 正常滚动
|
||||
// 2. 在列表滚动之后把剩余滚动吃掉,避免继续传递到 BottomSheet 去触发下拉关闭
|
||||
val nestedScrollConnection = remember {
|
||||
object : NestedScrollConnection {
|
||||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
||||
// 不消费任何事件,让 LazyVerticalGrid 先处理
|
||||
// 不在这里消费,先让 LazyVerticalGrid 自己处理滚动
|
||||
return Offset.Zero
|
||||
}
|
||||
|
||||
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
|
||||
// 消费 LazyVerticalGrid 处理后的剩余滚动事件,防止传递到 ModalBottomSheet
|
||||
// 列表滚动完之后,把剩余滚动(尤其是向下拖拽)全部吃掉,防止再传给 BottomSheet
|
||||
return available
|
||||
}
|
||||
|
||||
override suspend fun onPreFling(available: Velocity): Velocity {
|
||||
// 不消费惯性滚动,让 LazyVerticalGrid 先处理
|
||||
// 不抢在列表前面处理 fling,让 LazyVerticalGrid 先做惯性滚动
|
||||
return Velocity.Zero
|
||||
}
|
||||
|
||||
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
|
||||
// 消费 LazyVerticalGrid 处理后的剩余惯性滚动,防止传递到 ModalBottomSheet
|
||||
// 列表惯性滚动之后,把剩余的 fling 速度吃掉,避免带动 BottomSheet 下滑关闭
|
||||
return available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 网格列表 - 2列
|
||||
// 网格列表 - 2列(与草稿箱一样放在内容区域内部滚动)
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(2),
|
||||
modifier = Modifier
|
||||
@@ -291,7 +290,6 @@ fun ZodiacSelectBottomSheet(
|
||||
zodiacResId = zodiacResId,
|
||||
isSelected = zodiacResId == currentZodiacResId,
|
||||
onClick = {
|
||||
// 保存当前语言的星座文本
|
||||
model.zodiac = zodiacText
|
||||
onClose()
|
||||
}
|
||||
@@ -302,6 +300,7 @@ fun ZodiacSelectBottomSheet(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 保留原有的 ZodiacSelectScreen 用于导航路由(如果需要)
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@@ -336,9 +335,9 @@ fun ZodiacItem(
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(1.1f) // 增加宽高比,使高度相对更低
|
||||
.aspectRatio(1.1f)
|
||||
.shadow(
|
||||
elevation = if (isDarkMode) 8.dp else 2.dp, // 深色模式下更强的阴影
|
||||
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)
|
||||
)
|
||||
@@ -350,30 +349,27 @@ fun ZodiacItem(
|
||||
) {
|
||||
onClick()
|
||||
}
|
||||
.padding(horizontal = 24.dp, vertical = 12.dp), // 减小垂直padding,确保文本不被遮挡
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
// 星座图标 - 使用对应星座的图片
|
||||
Box(
|
||||
modifier = Modifier.size(100.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
// 直接把图标和文字放在灰色卡片内部,不再额外嵌套一层 Box
|
||||
Image(
|
||||
painter = painterResource(id = getZodiacImageResId(zodiacResId)),
|
||||
contentDescription = zodiac,
|
||||
modifier = Modifier.size(100.dp)
|
||||
// 图标稍微放大一些,让视觉更聚焦在星座图标上
|
||||
modifier = Modifier.size(96.dp)
|
||||
)
|
||||
}
|
||||
|
||||
// 星座名称 - 使用负间距让文本向上移动,与图标更靠近
|
||||
Spacer(modifier = Modifier.height(0.dp))
|
||||
|
||||
Text(
|
||||
text = zodiac,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = appColors.text,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.offset(y = (-20).dp) // 负间距,让文本进一步向上移动
|
||||
modifier = Modifier.offset(y = (-10).dp) // 再整体向上偏移 5dp(共 10dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
@@ -29,6 +30,7 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -40,6 +42,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import kotlinx.coroutines.launch
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
@@ -107,6 +110,8 @@ fun CommentModalContent(
|
||||
var softwareKeyboardController = LocalSoftwareKeyboardController.current
|
||||
var replyComment by remember { mutableStateOf<CommentEntity?>(null) }
|
||||
var shouldAutoFocus by remember { mutableStateOf(false) }
|
||||
val listState = rememberLazyListState()
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
LaunchedEffect(imePadding) {
|
||||
bottomPadding = imePadding.dp
|
||||
@@ -213,6 +218,9 @@ fun CommentModalContent(
|
||||
) {
|
||||
commentViewModel.order = it
|
||||
commentViewModel.reloadComment()
|
||||
scope.launch {
|
||||
listState.scrollToItem(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
Box(
|
||||
@@ -223,7 +231,8 @@ fun CommentModalContent(
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 16.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
state = listState
|
||||
) {
|
||||
item {
|
||||
CommentContent(
|
||||
|
||||
@@ -17,6 +17,7 @@ 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.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
@@ -30,6 +31,7 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -144,6 +146,8 @@ fun NewsCommentModal(
|
||||
var showCommentMenu by remember { mutableStateOf(false) }
|
||||
var contextComment by remember { mutableStateOf<CommentEntity?>(null) }
|
||||
var replyComment by remember { mutableStateOf<CommentEntity?>(null) }
|
||||
val listState = rememberLazyListState()
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
// 菜单弹窗
|
||||
if (showCommentMenu) {
|
||||
@@ -231,6 +235,9 @@ fun NewsCommentModal(
|
||||
) {
|
||||
commentViewModel.order = it
|
||||
commentViewModel.reloadComment()
|
||||
scope.launch {
|
||||
listState.scrollToItem(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,7 +276,9 @@ fun NewsCommentModal(
|
||||
)
|
||||
}
|
||||
} else {
|
||||
LazyColumn {
|
||||
LazyColumn(
|
||||
state = listState
|
||||
) {
|
||||
item {
|
||||
CommentContent(
|
||||
viewModel = commentViewModel,
|
||||
|
||||
@@ -347,6 +347,11 @@ fun VideoRecommendationItem(
|
||||
if (isVisible && shouldResumeAfterLifecyclePause) {
|
||||
pauseIconVisibleState = false
|
||||
exoPlayer.play()
|
||||
} else {
|
||||
// 未自动恢复播放时,如果当前可见且视频已暂停,则显示暂停图标
|
||||
if (isVisible && !exoPlayer.isPlaying) {
|
||||
pauseIconVisibleState = true
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
|
||||
@@ -549,6 +549,11 @@ fun VideoPlayer(
|
||||
exoPlayer.playWhenReady = true
|
||||
exoPlayer.play()
|
||||
pauseIconVisibleState.value = false
|
||||
} else {
|
||||
// 未自动恢复播放时,如果当前页面视频处于暂停状态,则显示暂停图标
|
||||
if (!exoPlayer.isPlaying) {
|
||||
pauseIconVisibleState.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user