Merge pull request #98 from Kevinlinpr/nagisa

修复星座和mbti选择界面上滑后会一直抖动、调整星座和mbti选择界面、、修复短视频在播放时退出后再进入会暂停但是不会显示暂停图标
This commit is contained in:
2025-12-02 12:00:06 +08:00
committed by GitHub
6 changed files with 357 additions and 338 deletions

View File

@@ -20,11 +20,13 @@ 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.layout.systemBars import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable 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.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.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
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 com.aiosman.ravenow.AppState import com.aiosman.ravenow.AppState
@@ -107,48 +110,35 @@ fun MbtiSelectBottomSheet(
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) 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( ModalBottomSheet(
onDismissRequest = onClose, onDismissRequest = onClose,
sheetState = sheetState, sheetState = sheetState,
containerColor = sheetBackgroundColor, containerColor = Color.Transparent,
dragHandle = null shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
dragHandle = {}
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.fillMaxHeight(0.95f) .fillMaxHeight()
.offset(y = offsetY) .padding(top = 8.dp)
.padding( ) {
start = 16.dp, Surface(
end = 16.dp, modifier = Modifier
bottom = 8.dp .fillMaxWidth()
) .fillMaxHeight()
.clip(RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)),
color = sheetBackgroundColor,
tonalElevation = 0.dp,
shadowElevation = 0.dp,
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.fillMaxHeight() .fillMaxHeight()
.padding(horizontal = 16.dp, vertical = 8.dp)
) { ) {
// 头部 - 使用 Box 实现绝对居中布局 // 头部
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -168,23 +158,27 @@ fun MbtiSelectBottomSheet(
} }
val cancelButtonContentColor = if (isDarkMode) Color(0xFFFFFFFF) else Color(0xFF404040) val cancelButtonContentColor = if (isDarkMode) Color(0xFFFFFFFF) else Color(0xFF404040)
// 左上角返回按钮 // 左上角返回按钮:整体「箭头 + 取消」在按钮内居中
Row( Box(
modifier = Modifier modifier = Modifier
.align(Alignment.CenterStart) .align(Alignment.CenterStart)
.height(36.dp) .width(91.dp)
.clip(RoundedCornerShape(18.dp)) .height(44.dp)
.clip(RoundedCornerShape(1000.dp))
.background( .background(
brush = Brush.linearGradient( brush = Brush.linearGradient(
colors = cancelButtonGradientColors colors = cancelButtonGradientColors
) )
) )
.noRippleClickable { onClose() } .noRippleClickable { onClose() },
.padding(horizontal = 8.dp), contentAlignment = Alignment.Center
) {
Row(
modifier = Modifier
.padding(horizontal = 12.dp, vertical = 4.dp),
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
// 左箭头图标
Image( Image(
painter = painterResource(id = R.drawable.rider_pro_back_icon), painter = painterResource(id = R.drawable.rider_pro_back_icon),
contentDescription = null, contentDescription = null,
@@ -192,61 +186,64 @@ fun MbtiSelectBottomSheet(
colorFilter = ColorFilter.tint(cancelButtonContentColor) colorFilter = ColorFilter.tint(cancelButtonContentColor)
) )
// "取消" 文字 Spacer(modifier = Modifier.width(4.dp))
Text( Text(
text = "取消", text = "取消",
fontSize = 17.sp, fontSize = 17.sp,
fontWeight = FontWeight.Medium, fontWeight = FontWeight.Medium,
color = cancelButtonContentColor, color = cancelButtonContentColor,
textAlign = androidx.compose.ui.text.style.TextAlign.Center textAlign = TextAlign.Center,
maxLines = 1,
overflow = TextOverflow.Clip
) )
} }
}
// 中间标题 - 绝对居中 // 中间标题
Text( Text(
text = stringResource(R.string.choose_mbti), text = stringResource(R.string.choose_mbti),
color = appColors.text, color = appColors.text,
fontSize = 20.sp, fontSize = 20.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
textAlign = androidx.compose.ui.text.style.TextAlign.Center textAlign = TextAlign.Center
) )
} }
Spacer(Modifier.height(12.dp)) Spacer(Modifier.height(12.dp))
// 创建 NestedScrollConnection 来阻止滚动事件向上传ModalBottomSheet // NestedScroll阻止滚动事件向上传到 BottomSheet
val nestedScrollConnection = remember { val nestedScrollConnection = remember {
object : NestedScrollConnection { object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
// 不消费任何事件,让 LazyColumn 先处理
return Offset.Zero return Offset.Zero
} }
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset { override fun onPostScroll(
// 消费 LazyColumn 处理后的剩余滚动事件,防止传递到 ModalBottomSheet consumed: Offset,
available: Offset,
source: NestedScrollSource
): Offset {
return available return available
} }
override suspend fun onPreFling(available: Velocity): Velocity { override suspend fun onPreFling(available: Velocity): Velocity {
// 不消费惯性滚动,让 LazyColumn 先处理
return Velocity.Zero return Velocity.Zero
} }
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
// 消费 LazyColumn 处理后的剩余惯性滚动,防止传递到 ModalBottomSheet
return available return available
} }
} }
} }
// MBTI解释文字背景色
val descriptionBackgroundColor = if (isDarkMode) { val descriptionBackgroundColor = if (isDarkMode) {
Color(0xFF2A2A2A) // 比 secondaryBackground (0xFF1C1C1C) 更亮的灰色 Color(0xFF2A2A2A)
} else { } else {
Color(0xFFFAF9FB) Color(0xFFFAF9FB)
} }
// 使用LazyColumn包裹解释文字和MBTI类型网格使它们一起滚动 // 列表:上面是说明文字,下面是 MBTI 网格
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -260,7 +257,7 @@ fun MbtiSelectBottomSheet(
), ),
verticalArrangement = Arrangement.spacedBy(16.dp) verticalArrangement = Arrangement.spacedBy(16.dp)
) { ) {
// MBTI解释文字 - 作为第一个item // 说明文字
item { item {
Box( Box(
modifier = Modifier modifier = Modifier
@@ -278,15 +275,17 @@ fun MbtiSelectBottomSheet(
} }
} }
// MBTI类型网格 - 手动创建2列网格布局 // MBTI 类型网格2 列)
itemsIndexed(MBTI_TYPES.chunked(2)) { rowIndex, rowItems -> itemsIndexed(MBTI_TYPES.chunked(2)) { rowIndex, rowItems ->
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .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) horizontalArrangement = Arrangement.spacedBy(10.dp)
) { ) {
rowItems.forEachIndexed { colIndex, mbti -> rowItems.forEach { mbti ->
Box( Box(
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)
) { ) {
@@ -294,14 +293,13 @@ fun MbtiSelectBottomSheet(
mbti = mbti, mbti = mbti,
isSelected = mbti == currentMbti, isSelected = mbti == currentMbti,
onClick = { onClick = {
// 保存MBTI类型
model.mbti = mbti model.mbti = mbti
onClose() onClose()
} }
) )
} }
} }
// 如果这一行只有1个item添加一个空的Spacer来保持布局
if (rowItems.size == 1) { if (rowItems.size == 1) {
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
} }
@@ -312,6 +310,7 @@ fun MbtiSelectBottomSheet(
} }
} }
} }
}
// 保留原有的 MbtiSelectScreen 用于导航路由(如果需要) // 保留原有的 MbtiSelectScreen 用于导航路由(如果需要)
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@@ -358,30 +357,26 @@ fun MbtiItem(
) { ) {
onClick() onClick()
} }
.padding(horizontal = 24.dp, vertical = 12.dp), .padding(horizontal = 16.dp, vertical = 12.dp),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center verticalArrangement = Arrangement.Center
) { ) {
// MBTI图标 - 使用占位图片 // 直接把 MBTI 图标和文字放在灰色卡片内部,布局与星座保持一致
Box(
modifier = Modifier.size(100.dp),
contentAlignment = Alignment.Center
) {
Image( Image(
painter = painterResource(id = getMbtiImageResId(mbti, isDarkMode)), painter = painterResource(id = getMbtiImageResId(mbti, isDarkMode)),
contentDescription = mbti, contentDescription = mbti,
modifier = Modifier.size(100.dp) modifier = Modifier.size(96.dp)
) )
}
// MBTI名称 - 使用负间距让文本向上移动,与图标更靠近 Spacer(modifier = Modifier.height(0.dp))
Text( Text(
text = mbti, text = mbti,
fontSize = 14.sp, fontSize = 14.sp,
fontWeight = FontWeight.Medium, fontWeight = FontWeight.Medium,
color = appColors.text, color = appColors.text,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.offset(y = (-20).dp) modifier = Modifier.offset(y = (-10).dp)
) )
} }
} }

View File

@@ -28,6 +28,7 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable 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.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.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
@@ -135,48 +137,36 @@ fun ZodiacSelectBottomSheet(
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) 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( ModalBottomSheet(
onDismissRequest = onClose, onDismissRequest = onClose,
sheetState = sheetState, sheetState = sheetState,
containerColor = sheetBackgroundColor, // 根据主题自适应背景 // 对齐发布动态草稿箱样式:底层透明,内容区域自己绘制圆角和背景
dragHandle = null containerColor = Color.Transparent,
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
dragHandle = {}
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.fillMaxHeight(0.95f) .fillMaxHeight()
.offset(y = offsetY) .padding(top = 8.dp)
.padding( ) {
start = 16.dp, Surface(
end = 16.dp, modifier = Modifier
bottom = 8.dp .fillMaxWidth()
) .fillMaxHeight()
.clip(RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)),
color = sheetBackgroundColor,
tonalElevation = 0.dp,
shadowElevation = 0.dp,
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.fillMaxHeight() .fillMaxHeight()
.padding(horizontal = 16.dp, vertical = 8.dp)
) { ) {
// 头部 - 使用 Box 实现绝对居中布局 // 头部 - 使用 Box 实现绝对居中布局(对齐草稿箱样式)
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -196,24 +186,28 @@ fun ZodiacSelectBottomSheet(
} }
val cancelButtonContentColor = if (isDarkMode) Color(0xFFFFFFFF) else Color(0xFF404040) val cancelButtonContentColor = if (isDarkMode) Color(0xFFFFFFFF) else Color(0xFF404040)
// 左上角返回按钮 - 根据 Swift 代码样式,带淡灰色渐变背景 // 左上角返回按钮:参考 iOS 设计,整体「箭头 + 取消」在 91x44 的按钮内居中
Row( Box(
modifier = Modifier modifier = Modifier
.align(Alignment.CenterStart) .align(Alignment.CenterStart)
.height(36.dp) .width(91.dp)
.clip(RoundedCornerShape(18.dp)) // 圆角 100.0 在 36dp 高度下接近完全圆角 .height(44.dp)
.clip(RoundedCornerShape(1000.dp))
.background( .background(
brush = Brush.linearGradient( brush = Brush.linearGradient(
colors = cancelButtonGradientColors colors = cancelButtonGradientColors
// 不指定 start 和 end默认从左上到右下
) )
) )
.noRippleClickable { onClose() } .noRippleClickable { onClose() },
.padding(horizontal = 8.dp), // 内部 padding 确保内容不贴边 contentAlignment = Alignment.Center
) {
Row(
modifier = Modifier
// 不再固定宽度,让内容自然占位,避免裁剪掉“消”字
.padding(horizontal = 12.dp, vertical = 4.dp),
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
// 左箭头图标
Image( Image(
painter = painterResource(id = R.drawable.rider_pro_back_icon), painter = painterResource(id = R.drawable.rider_pro_back_icon),
contentDescription = null, contentDescription = null,
@@ -221,17 +215,20 @@ fun ZodiacSelectBottomSheet(
colorFilter = ColorFilter.tint(cancelButtonContentColor) colorFilter = ColorFilter.tint(cancelButtonContentColor)
) )
// "取消" 文字 Spacer(modifier = Modifier.width(4.dp))
Text( Text(
text = "取消", text = "取消",
fontSize = 17.sp, fontSize = 17.sp,
fontWeight = FontWeight.Medium, fontWeight = FontWeight.Medium,
color = cancelButtonContentColor, 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(
text = stringResource(R.string.choose_zodiac), text = stringResource(R.string.choose_zodiac),
color = appColors.text, color = appColors.text,
@@ -243,32 +240,34 @@ fun ZodiacSelectBottomSheet(
Spacer(Modifier.height(12.dp)) Spacer(Modifier.height(12.dp))
// 创建 NestedScrollConnection 来阻止滚动事件向上传播到 ModalBottomSheet // 创建 NestedScrollConnection
// 1. 不抢在列表前面消费事件,让 LazyVerticalGrid 正常滚动
// 2. 在列表滚动之后把剩余滚动吃掉,避免继续传递到 BottomSheet 去触发下拉关闭
val nestedScrollConnection = remember { val nestedScrollConnection = remember {
object : NestedScrollConnection { object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
// 不消费任何事件,让 LazyVerticalGrid 先处理 // 不在这里消费,先让 LazyVerticalGrid 自己处理滚动
return Offset.Zero return Offset.Zero
} }
override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset { override fun onPostScroll(consumed: Offset, available: Offset, source: NestedScrollSource): Offset {
// 消费 LazyVerticalGrid 处理后的剩余滚动事件,防止传递到 ModalBottomSheet // 列表滚动完之后,把剩余滚动(尤其是向下拖拽)全部吃掉,防止再传给 BottomSheet
return available return available
} }
override suspend fun onPreFling(available: Velocity): Velocity { override suspend fun onPreFling(available: Velocity): Velocity {
// 不消费惯性滚动,让 LazyVerticalGrid 先处理 // 不抢在列表前面处理 fling,让 LazyVerticalGrid 先做惯性滚动
return Velocity.Zero return Velocity.Zero
} }
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
// 消费 LazyVerticalGrid 处理后的剩余惯性滚动,防止传递到 ModalBottomSheet // 列表惯性滚动之后,把剩余的 fling 速度吃掉,避免带动 BottomSheet 下滑关闭
return available return available
} }
} }
} }
// 网格列表 - 2列 // 网格列表 - 2列(与草稿箱一样放在内容区域内部滚动)
LazyVerticalGrid( LazyVerticalGrid(
columns = GridCells.Fixed(2), columns = GridCells.Fixed(2),
modifier = Modifier modifier = Modifier
@@ -291,7 +290,6 @@ fun ZodiacSelectBottomSheet(
zodiacResId = zodiacResId, zodiacResId = zodiacResId,
isSelected = zodiacResId == currentZodiacResId, isSelected = zodiacResId == currentZodiacResId,
onClick = { onClick = {
// 保存当前语言的星座文本
model.zodiac = zodiacText model.zodiac = zodiacText
onClose() onClose()
} }
@@ -302,6 +300,7 @@ fun ZodiacSelectBottomSheet(
} }
} }
} }
}
// 保留原有的 ZodiacSelectScreen 用于导航路由(如果需要) // 保留原有的 ZodiacSelectScreen 用于导航路由(如果需要)
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@@ -336,9 +335,9 @@ fun ZodiacItem(
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.aspectRatio(1.1f) // 增加宽高比,使高度相对更低 .aspectRatio(1.1f)
.shadow( .shadow(
elevation = if (isDarkMode) 8.dp else 2.dp, // 深色模式下更强的阴影 elevation = if (isDarkMode) 8.dp else 2.dp,
shape = RoundedCornerShape(21.dp), shape = RoundedCornerShape(21.dp),
spotColor = if (isDarkMode) Color.Black.copy(alpha = 0.5f) else Color.Black.copy(alpha = 0.1f) spotColor = if (isDarkMode) Color.Black.copy(alpha = 0.5f) else Color.Black.copy(alpha = 0.1f)
) )
@@ -350,30 +349,27 @@ fun ZodiacItem(
) { ) {
onClick() onClick()
} }
.padding(horizontal = 24.dp, vertical = 12.dp), // 减小垂直padding确保文本不被遮挡 .padding(horizontal = 16.dp, vertical = 12.dp),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center verticalArrangement = Arrangement.Center
) { ) {
// 星座图标 - 使用对应星座的图片 // 直接把图标和文字放在灰色卡片内部,不再额外嵌套一层 Box
Box(
modifier = Modifier.size(100.dp),
contentAlignment = Alignment.Center
) {
Image( Image(
painter = painterResource(id = getZodiacImageResId(zodiacResId)), painter = painterResource(id = getZodiacImageResId(zodiacResId)),
contentDescription = zodiac, contentDescription = zodiac,
modifier = Modifier.size(100.dp) // 图标稍微放大一些,让视觉更聚焦在星座图标上
modifier = Modifier.size(96.dp)
) )
}
// 星座名称 - 使用负间距让文本向上移动,与图标更靠近 Spacer(modifier = Modifier.height(0.dp))
Text( Text(
text = zodiac, text = zodiac,
fontSize = 14.sp, fontSize = 14.sp,
fontWeight = FontWeight.Medium, fontWeight = FontWeight.Medium,
color = appColors.text, color = appColors.text,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.offset(y = (-20).dp) // 负间距,让文本进一步向上移动 modifier = Modifier.offset(y = (-10).dp) // 再整体向上偏移 5dp共 10dp
) )
} }
} }

View File

@@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
@@ -29,6 +30,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue 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
@@ -40,6 +42,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
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 kotlinx.coroutines.launch
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@@ -107,6 +110,8 @@ fun CommentModalContent(
var softwareKeyboardController = LocalSoftwareKeyboardController.current var softwareKeyboardController = LocalSoftwareKeyboardController.current
var replyComment by remember { mutableStateOf<CommentEntity?>(null) } var replyComment by remember { mutableStateOf<CommentEntity?>(null) }
var shouldAutoFocus by remember { mutableStateOf(false) } var shouldAutoFocus by remember { mutableStateOf(false) }
val listState = rememberLazyListState()
val scope = rememberCoroutineScope()
LaunchedEffect(imePadding) { LaunchedEffect(imePadding) {
bottomPadding = imePadding.dp bottomPadding = imePadding.dp
@@ -213,6 +218,9 @@ fun CommentModalContent(
) { ) {
commentViewModel.order = it commentViewModel.order = it
commentViewModel.reloadComment() commentViewModel.reloadComment()
scope.launch {
listState.scrollToItem(0)
}
} }
} }
Box( Box(
@@ -223,7 +231,8 @@ fun CommentModalContent(
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp),
state = listState
) { ) {
item { item {
CommentContent( CommentContent(

View File

@@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close 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.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue 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
@@ -144,6 +146,8 @@ fun NewsCommentModal(
var showCommentMenu by remember { mutableStateOf(false) } var showCommentMenu by remember { mutableStateOf(false) }
var contextComment by remember { mutableStateOf<CommentEntity?>(null) } var contextComment by remember { mutableStateOf<CommentEntity?>(null) }
var replyComment by remember { mutableStateOf<CommentEntity?>(null) } var replyComment by remember { mutableStateOf<CommentEntity?>(null) }
val listState = rememberLazyListState()
val scope = rememberCoroutineScope()
// 菜单弹窗 // 菜单弹窗
if (showCommentMenu) { if (showCommentMenu) {
@@ -231,6 +235,9 @@ fun NewsCommentModal(
) { ) {
commentViewModel.order = it commentViewModel.order = it
commentViewModel.reloadComment() commentViewModel.reloadComment()
scope.launch {
listState.scrollToItem(0)
}
} }
} }
} }
@@ -269,7 +276,9 @@ fun NewsCommentModal(
) )
} }
} else { } else {
LazyColumn { LazyColumn(
state = listState
) {
item { item {
CommentContent( CommentContent(
viewModel = commentViewModel, viewModel = commentViewModel,

View File

@@ -347,6 +347,11 @@ fun VideoRecommendationItem(
if (isVisible && shouldResumeAfterLifecyclePause) { if (isVisible && shouldResumeAfterLifecyclePause) {
pauseIconVisibleState = false pauseIconVisibleState = false
exoPlayer.play() exoPlayer.play()
} else {
// 未自动恢复播放时,如果当前可见且视频已暂停,则显示暂停图标
if (isVisible && !exoPlayer.isPlaying) {
pauseIconVisibleState = true
}
} }
} }
else -> {} else -> {}

View File

@@ -549,6 +549,11 @@ fun VideoPlayer(
exoPlayer.playWhenReady = true exoPlayer.playWhenReady = true
exoPlayer.play() exoPlayer.play()
pauseIconVisibleState.value = false pauseIconVisibleState.value = false
} else {
// 未自动恢复播放时,如果当前页面视频处于暂停状态,则显示暂停图标
if (!exoPlayer.isPlaying) {
pauseIconVisibleState.value = true
}
} }
} }