From 2f41c61b7e573241ddbf36b09acc7a16cb95976f Mon Sep 17 00:00:00 2001 From: AllenTom Date: Mon, 10 Nov 2025 23:34:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=99=BA=E8=83=BD=E4=BD=93?= =?UTF-8?q?=EF=BC=88Agent=EF=BC=89=E5=B1=95=E7=A4=BA=E8=BD=AE=E6=92=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将原有的分页网格布局,重构为全屏卡片式轮播。 - 每个智能体以带有背景大图的卡片展示,增强视觉效果。 - 在卡片底部增加了渐变遮罩、标题和描述,并在底部中央添加了“聊天”按钮,以改善用户交互和界面美观度。 - 调整了轮播的尺寸和间距,使其自适应屏幕宽度。 --- .../aiosman/ravenow/ui/index/tabs/ai/Agent.kt | 186 +++++++++++++----- 1 file changed, 132 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/ai/Agent.kt b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/ai/Agent.kt index 9527d0d..fc235ee 100644 --- a/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/ai/Agent.kt +++ b/app/src/main/java/com/aiosman/ravenow/ui/index/tabs/ai/Agent.kt @@ -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,73 +585,147 @@ fun AgentCardSquare( @Composable fun AgentViewPagerSection(agentItems: List,viewModel: AgentViewModel) { val AppColors = LocalAppTheme.current + if (agentItems.isEmpty()) return - // 每页显示5个agent - val itemsPerPage = 5 - val totalPages = (agentItems.size + itemsPerPage - 1) / itemsPerPage + 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 - if (totalPages > 0) { - val pagerState = rememberPagerState(pageCount = { totalPages }) + Column { + Box( + modifier = Modifier + .height(pagerHeight) + ) { + HorizontalPager( + state = pagerState, + modifier = Modifier.fillMaxSize(), + 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)) - Column { - // Agent内容 - Box( - modifier = Modifier - .height(310.dp) - ) { - HorizontalPager( - state = pagerState, - modifier = Modifier.fillMaxSize(), - contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 4.dp), - pageSpacing = 0.dp - ) { page -> - // 计算当前页面的偏移量 - val pageOffset = ( - (pagerState.currentPage - page) + pagerState - .currentPageOffsetFraction - ).coerceIn(-1f, 1f) + AgentLargeCard( + agentItem = agentItems[page], + viewModel = viewModel, + navController = LocalNavController.current, + modifier = Modifier + .graphicsLayer { + scaleX = scale + scaleY = scale + } + ) + } + } + } +} - // 根据偏移量计算缩放比例 - val scale = 1f - (0.1f * kotlin.math.abs(pageOffset)) +@SuppressLint("SuspiciousIndentation") +@Composable +fun AgentLargeCard( + agentItem: AgentItem, + viewModel: AgentViewModel, + navController: NavHostController, + modifier: Modifier = Modifier +) { + val AppColors = LocalAppTheme.current + var lastClickTime by remember { mutableStateOf(0L) } - AgentPage( - viewModel = viewModel, - agentItems = agentItems.drop(page * itemsPerPage).take(itemsPerPage), - page = page, - modifier = Modifier - .height(310.dp) - .graphicsLayer { - scaleX = scale - scaleY = scale - }, - navController = LocalNavController.current, - ) + 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 + ) - // 指示器 - Row( + // 底部渐变与文字 + 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() - .height(30.dp) - .padding(top = 12.dp), - horizontalArrangement = androidx.compose.foundation.layout.Arrangement.Center + .padding(bottom = 56.dp) // 为底部聊天按钮预留空间 ) { - repeat(totalPages) { index -> - 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 - ) - ) - } + 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 + ) } } + + // 底部居中 Chat 按钮 + Box( + modifier = Modifier + .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 + ) + } } }