优化智能体(Agent)展示轮播
- 将原有的分页网格布局,重构为全屏卡片式轮播。 - 每个智能体以带有背景大图的卡片展示,增强视觉效果。 - 在卡片底部增加了渐变遮罩、标题和描述,并在底部中央添加了“聊天”按钮,以改善用户交互和界面美观度。 - 调整了轮播的尺寸和间距,使其自适应屏幕宽度。
This commit is contained in:
@@ -88,6 +88,10 @@ import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.compose.foundation.lazy.grid.items as gridItems
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
|
||||
// 检测是否接近列表底部的扩展函数
|
||||
fun LazyListState.isScrolledToEnd(buffer: Int = 3): Boolean {
|
||||
@@ -581,72 +585,146 @@ fun AgentCardSquare(
|
||||
@Composable
|
||||
fun AgentViewPagerSection(agentItems: List<AgentItem>,viewModel: AgentViewModel) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
if (agentItems.isEmpty()) return
|
||||
|
||||
// 每页显示5个agent
|
||||
val itemsPerPage = 5
|
||||
val totalPages = (agentItems.size + itemsPerPage - 1) / itemsPerPage
|
||||
|
||||
if (totalPages > 0) {
|
||||
val pagerState = rememberPagerState(pageCount = { totalPages })
|
||||
val pagerState = rememberPagerState(pageCount = { agentItems.size })
|
||||
val screenWidth = LocalConfiguration.current.screenWidthDp.dp
|
||||
val cardAspect = 1133.5f / 846.4f
|
||||
// 外层 LazyColumn 左右各 8dp + Pager contentPadding 左右各 20dp
|
||||
val horizontalPaddings = 56.dp
|
||||
val pagerHeight = (screenWidth - horizontalPaddings) * cardAspect
|
||||
|
||||
Column {
|
||||
// Agent内容
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(310.dp)
|
||||
.height(pagerHeight)
|
||||
) {
|
||||
HorizontalPager(
|
||||
state = pagerState,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 4.dp),
|
||||
pageSpacing = 0.dp
|
||||
contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 20.dp),
|
||||
pageSpacing = 12.dp
|
||||
) { page ->
|
||||
// 计算当前页面的偏移量
|
||||
// 缩放效果
|
||||
val pageOffset = (
|
||||
(pagerState.currentPage - page) + pagerState
|
||||
.currentPageOffsetFraction
|
||||
).coerceIn(-1f, 1f)
|
||||
val scale = 1f - (0.06f * kotlin.math.abs(pageOffset))
|
||||
|
||||
// 根据偏移量计算缩放比例
|
||||
val scale = 1f - (0.1f * kotlin.math.abs(pageOffset))
|
||||
|
||||
AgentPage(
|
||||
AgentLargeCard(
|
||||
agentItem = agentItems[page],
|
||||
viewModel = viewModel,
|
||||
agentItems = agentItems.drop(page * itemsPerPage).take(itemsPerPage),
|
||||
page = page,
|
||||
navController = LocalNavController.current,
|
||||
modifier = Modifier
|
||||
.height(310.dp)
|
||||
.graphicsLayer {
|
||||
scaleX = scale
|
||||
scaleY = scale
|
||||
},
|
||||
navController = LocalNavController.current,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SuspiciousIndentation")
|
||||
@Composable
|
||||
fun AgentLargeCard(
|
||||
agentItem: AgentItem,
|
||||
viewModel: AgentViewModel,
|
||||
navController: NavHostController,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val AppColors = LocalAppTheme.current
|
||||
var lastClickTime by remember { mutableStateOf(0L) }
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(846.4f / 1133.5f)
|
||||
.clip(RoundedCornerShape(24.dp))
|
||||
.noRippleClickable {
|
||||
if (DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
|
||||
viewModel.goToProfile(agentItem.openId, navController)
|
||||
}) {
|
||||
lastClickTime = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
) {
|
||||
// 背景大图
|
||||
CustomAsyncImage(
|
||||
imageUrl = agentItem.avatar,
|
||||
contentDescription = agentItem.title,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentScale = androidx.compose.ui.layout.ContentScale.Crop
|
||||
)
|
||||
|
||||
// 底部渐变与文字
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
Brush.verticalGradient(
|
||||
0f to Color.Transparent,
|
||||
1f to Color(0xB2000000)
|
||||
)
|
||||
)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 56.dp) // 为底部聊天按钮预留空间
|
||||
) {
|
||||
androidx.compose.material3.Text(
|
||||
text = agentItem.title,
|
||||
color = Color.White,
|
||||
fontSize = 20.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W700,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
androidx.compose.material3.Text(
|
||||
text = agentItem.desc,
|
||||
color = Color.White.copy(alpha = 0.92f),
|
||||
fontSize = 14.sp,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 指示器
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(30.dp)
|
||||
.padding(top = 12.dp),
|
||||
horizontalArrangement = androidx.compose.foundation.layout.Arrangement.Center
|
||||
) {
|
||||
repeat(totalPages) { index ->
|
||||
// 底部居中 Chat 按钮
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 4.dp)
|
||||
.size(3.dp)
|
||||
.background(
|
||||
color = if (pagerState.currentPage == index) AppColors.text else AppColors.secondaryText.copy(
|
||||
alpha = 0.3f
|
||||
),
|
||||
shape = androidx.compose.foundation.shape.CircleShape
|
||||
)
|
||||
)
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(bottom = 16.dp)
|
||||
.widthIn(min = 180.dp)
|
||||
.fillMaxWidth(0.65f)
|
||||
.height(44.dp)
|
||||
.background(AppColors.text, RoundedCornerShape(22.dp))
|
||||
.noRippleClickable {
|
||||
if (DebounceUtils.simpleDebounceClick(lastClickTime, 500L) {
|
||||
if (GuestLoginCheckOut.needLogin(GuestLoginCheckOutScene.CHAT_WITH_AGENT)) {
|
||||
navController.navigate(NavigationRoute.Login.route)
|
||||
} else {
|
||||
viewModel.createSingleChat(agentItem.openId)
|
||||
viewModel.goToChatAi(agentItem.openId, navController)
|
||||
}
|
||||
}) {
|
||||
lastClickTime = System.currentTimeMillis()
|
||||
}
|
||||
},
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
androidx.compose.material3.Text(
|
||||
text = stringResource(R.string.chat),
|
||||
color = AppColors.background,
|
||||
fontSize = 16.sp,
|
||||
fontWeight = androidx.compose.ui.text.font.FontWeight.W600
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user