news 2026/4/20 9:54:37

Compose笔记(六十九)--Pager

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Compose笔记(六十九)--Pager

这一节主要了解一下Compose中的Pager,在Jetpack Compose开发中,Pager是用于实现滑动页面集合的核心组件,支持水平(HorizontalPager)和垂直(VerticalPager)方向的滑动,能够灵活管理页面内容、状态和交互。简单总结:

API:
HorizontalPager/VerticalPager:核心组件,分别实现横向 / 纵向翻页
rememberPagerState:创建并记忆 Pager 状态,包含当前页码、滑动偏移等
PagerScope:页面作用域,提供 pageOffset 等页面滑动状态参数
PageSize:定义页面尺寸
PagerSnapDistance:定义滑动后吸附到页面的距离

场景:
1 图片轮播 在电商、新闻等应用中,顶部展示多张图片并自动轮播,用户可手动滑动切换。
2 引导页 应用首次启动时展示多页引导内容,用户滑动浏览后进入主界面。
3 分类标签页 顶部标签栏切换时,下方内容同步滑动

栗子:

implementation("io.coil-kt:coil-compose:2.5.0")
// 权限 <uses-permission android:name="android.permission.INTERNET" />
import androidx.compose.runtime.Composable import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PageSize import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text 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 import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.scale import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.rememberAsyncImagePainter import kotlinx.coroutines.delay import kotlinx.coroutines.launch data class PagerItem( val id: Int, val title: String, val imageUrl: String, val bgColor: androidx.compose.ui.graphics.Color ) fun Float.format(digits: Int): String = "%.${digits}f".format(this) @Composable fun PagerDemo() { val pagerData = listOf( PagerItem(1, "商品A", "https://picsum.photos/800/400?random=1", androidx.compose.ui.graphics.Color(0xFF6495ED)), PagerItem(2, "商品B", "https://picsum.photos/800/400?random=2", androidx.compose.ui.graphics.Color(0xFF90EE90)), PagerItem(3, "商品C", "https://picsum.photos/800/400?random=3", androidx.compose.ui.graphics.Color(0xFFFFB6C1)), PagerItem(4, "商品D", "https://picsum.photos/800/400?random=4", androidx.compose.ui.graphics.Color(0xFFFFD700)) ) Surface(modifier = Modifier.fillMaxSize()) { val pagerState = rememberPagerState( initialPage = 0, pageCount = { pagerData.size } ) val coroutineScope = rememberCoroutineScope() var slideOffset by remember { mutableStateOf(0.0f) } LaunchedEffect(pagerState.currentPage, pagerState.currentPageOffsetFraction) { slideOffset = pagerState.currentPage + pagerState.currentPageOffsetFraction } Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "滑动进度:${slideOffset.format(2)}", fontSize = 16.sp, modifier = Modifier.padding(16.dp) ) HorizontalPager( state = pagerState, modifier = Modifier .weight(1f) .padding(horizontal = 20.dp), pageSize = PageSize.Fill, pageSpacing = 16.dp, contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 20.dp) ) { pageIndex -> val item = pagerData[pageIndex] val pageOffset = pagerState.currentPageOffsetFraction val scale by animateFloatAsState( targetValue = if (pageIndex == pagerState.currentPage) 1f else 0.9f, label = "pageScale" ) val alpha by animateFloatAsState( targetValue = if (pageIndex == pagerState.currentPage) 1f else 0.7f, label = "pageAlpha" ) var isLoading by remember { mutableStateOf(true) } LaunchedEffect(pageIndex) { delay(300) isLoading = false } Box( modifier = Modifier .fillMaxSize() .scale(scale) .alpha(alpha) .background(item.bgColor, MaterialTheme.shapes.medium) .padding(16.dp), contentAlignment = Alignment.Center ) { if (isLoading) { Text(text = "加载中...", color = androidx.compose.ui.graphics.Color.White) } else { Column( horizontalAlignment = Alignment.CenterHorizontally ) { Image( painter = rememberAsyncImagePainter(model = item.imageUrl), contentDescription = item.title, modifier = Modifier .size(200.dp, 150.dp) .padding(bottom = 16.dp), contentScale = ContentScale.Crop ) Text( text = item.title, fontSize = 20.sp, color = androidx.compose.ui.graphics.Color.White ) } } } } Column( modifier = Modifier.padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Row( horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.padding(bottom = 16.dp) ) { pagerData.forEachIndexed { index, _ -> val isSelected = index == pagerState.currentPage Box( modifier = Modifier .size(if (isSelected) 12.dp else 8.dp) .background( color = if (isSelected) androidx.compose.ui.graphics.Color.Blue else androidx.compose.ui.graphics.Color.Gray, shape = CircleShape ) ) } } Row( horizontalArrangement = Arrangement.spacedBy(16.dp) ) { Button( onClick = { coroutineScope.launch { if (pagerState.currentPage > 0) { pagerState.animateScrollToPage(pagerState.currentPage - 1) } } }, enabled = pagerState.currentPage > 0 ) { Text(text = "上一页") } Button( onClick = { coroutineScope.launch { if (pagerState.currentPage < pagerData.size - 1) { pagerState.animateScrollToPage(pagerState.currentPage + 1) } } }, enabled = pagerState.currentPage < pagerData.size - 1 ) { Text(text = "下一页") } } } } } }
import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.VerticalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.rememberAsyncImagePainter @Composable fun PagerDemo() { val imageUrls = listOf( "https://picsum.photos/800/1200?random=1", "https://picsum.photos/800/1200?random=2", "https://picsum.photos/800/1200?random=3" ) val pagerState = rememberPagerState( initialPage = 0, pageCount = { imageUrls.size } ) Surface(modifier = Modifier.fillMaxSize()) { VerticalPager( state = pagerState, modifier = Modifier.fillMaxSize(), pageSize = androidx.compose.foundation.pager.PageSize.Fill ) { pageIndex -> Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Image( painter = rememberAsyncImagePainter(model = imageUrls[pageIndex]), contentDescription = "商品图片${pageIndex + 1}", modifier = Modifier .fillMaxSize() .padding(20.dp), contentScale = ContentScale.Crop ) Text( text = "${pageIndex + 1}/${imageUrls.size}", fontSize = 20.sp, color = Color.White, modifier = Modifier .background(Color.Black.copy(alpha = 0.5f)) .padding(8.dp) .align(Alignment.BottomCenter) ) } } } }

注意:
1 页面预加载与优化 默认仅加载可见页面,通过beyondViewportPageCount设置屏幕外预加载页面数
2 状态管理与滚动监听 使用LaunchedEffect(pagerState.currentPage)监听页面变化,避免在pageContent中直接监听导致重复重组。
3 滚动控制 滚动需在协程中调用

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 12:47:40

51单片机串口通信程序详解

51单片机串口通信程序源码&#xff0c;注释详细&#xff0c;包含接收和传输代码&#xff0c;以及文档说明在51单片机的应用中&#xff0c;串口通信是非常重要的功能&#xff0c;它可以实现单片机与其他设备的数据交互。今天就来详细剖析一下51单片机串口通信的程序源码&#xf…

作者头像 李华
网站建设 2026/4/20 2:51:22

开发基于大模型的金融专业教学案例动态生成器

开发基于大模型的金融专业教学案例动态生成器关键词&#xff1a;大模型、金融专业教学案例、动态生成器、自然语言处理、人工智能教育应用摘要&#xff1a;本文聚焦于开发基于大模型的金融专业教学案例动态生成器。首先介绍了该项目的背景&#xff0c;包括目的、预期读者、文档…

作者头像 李华
网站建设 2026/4/18 14:07:51

node.js基于vue的协同过滤算法的学生就业推荐系统管理系统_un62e6l3

文章目录摘要功能模块技术实现创新点项目技术介绍开发工具和技术简介nodejs类核心代码部分展示结论源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;摘要 该系统基于Node.js与Vue.js构建&#xff0c;旨在通过协同过滤算法为学生提供个性…

作者头像 李华
网站建设 2026/4/19 11:08:32

3.30 视频内容理解:InternVideo,让AI理解视频中的内容

3.30 视频内容理解:InternVideo,让AI理解视频中的内容 引言 视频内容理解是AI的重要能力,InternVideo是视频理解领域的先进模型。本文将深入解析视频内容理解的实现方法。 一、视频理解挑战 1.1 挑战概述 # 视频理解挑战 def video_understanding_challenges():"&…

作者头像 李华
网站建设 2026/4/18 21:20:24

【值得收藏】大模型新技能:三步提取法构建可解释AI的因果图谱

本研究提出了一种利用大语言模型(LLM)代理从文本中自动提取因果反馈模糊认知图谱(FCM)的创新方法。通过三步系统指令&#xff0c;LLM能识别文本中的关键概念和因果关系&#xff0c;构建动态系统模型并预测平衡状态。该方法具有自动化、可扩展性和可验证性优势&#xff0c;能揭示…

作者头像 李华