如要以左右或上下方式翻閱內容,可以分別使用 HorizontalPager
和 VerticalPager
可組合函式。這些可組合項的功能與 View 系統中的 ViewPager
類似。根據預設,HorizontalPager
會占滿整個畫面寬度,VerticalPager
則會占滿整個高度,且分頁器一次只會滑動一頁。這些預設值都可以設定。
HorizontalPager
如要建立可左右水平捲動的分頁器,請使用 HorizontalPager
:
HorizontalPager
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
VerticalPager
如要建立可向上和向下捲動的分頁器,請使用 VerticalPager
:
VerticalPager
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
延遲建立
HorizontalPager
和 VerticalPager
中的頁面都會在需要時延遲組合及配置。當使用者捲動瀏覽網頁時,可組合函式會移除不再需要的網頁。
在螢幕外載入更多網頁
根據預設,分頁器只會載入螢幕上顯示的頁面。如要載入更多畫面外的網頁,請將 beyondBoundsPageCount
設為大於零的值。
捲動至分頁器中的項目
如要在分頁器中捲動至特定頁面,請使用 rememberPagerState()
建立 PagerState
物件,並將其做為 state
參數傳遞至分頁器。您可以在這個狀態下呼叫 PagerState#scrollToPage()
,方法是在 CoroutineScope
內:
val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier .fillMaxWidth() .height(100.dp) ) } // scroll to page val coroutineScope = rememberCoroutineScope() Button(onClick = { coroutineScope.launch { // Call scroll to on pagerState pagerState.scrollToPage(5) } }, modifier = Modifier.align(Alignment.BottomCenter)) { Text("Jump to Page 5") }
如要為頁面建立動畫,請使用 PagerState#animateScrollToPage()
函式:
val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier .fillMaxWidth() .height(100.dp) ) } // scroll to page val coroutineScope = rememberCoroutineScope() Button(onClick = { coroutineScope.launch { // Call scroll to on pagerState pagerState.animateScrollToPage(5) } }, modifier = Modifier.align(Alignment.BottomCenter)) { Text("Jump to Page 5") }
接收網頁狀態變更通知
PagerState
包含三個屬性,可提供網頁相關資訊:currentPage
、settledPage
和 targetPage
。
currentPage
:最靠近貼齊位置的頁面。根據預設,對齊位置位於版面配置的開頭。settledPage
:未執行動畫或捲動時的頁碼。這與currentPage
屬性不同,因為如果網頁夠接近貼齊位置,currentPage
會立即更新,但settledPage
會維持不變,直到所有動畫執行完畢為止。targetPage
:捲動動作的建議停止位置。
您可以使用 snapshotFlow
函式觀察這些變數的變化,並做出反應。舉例來說,如要在每次網頁變更時傳送數據分析事件,可以執行下列操作:
val pagerState = rememberPagerState(pageCount = { 10 }) LaunchedEffect(pagerState) { // Collect from the a snapshotFlow reading the currentPage snapshotFlow { pagerState.currentPage }.collect { page -> // Do something with each page change, for example: // viewModel.sendPageSelectedEvent(page) Log.d("Page change", "Page changed to $page") } } VerticalPager( state = pagerState, ) { page -> Text(text = "Page: $page") }
新增頁碼指標
如要在頁面中新增指標,請使用 PagerState
物件取得資訊,瞭解從多個頁面中選取的頁面,並繪製自訂指標。
舉例來說,如要使用簡單的圓圈指標,可以重複圓圈數量,並根據頁面是否已選取,使用 pagerState.currentPage
變更圓圈顏色:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, modifier = Modifier.fillMaxSize() ) { page -> // Our page content Text( text = "Page: $page", ) } Row( Modifier .wrapContentHeight() .fillMaxWidth() .align(Alignment.BottomCenter) .padding(bottom = 8.dp), horizontalArrangement = Arrangement.Center ) { repeat(pagerState.pageCount) { iteration -> val color = if (pagerState.currentPage == iteration) Color.DarkGray else Color.LightGray Box( modifier = Modifier .padding(2.dp) .clip(CircleShape) .background(color) .size(16.dp) ) } }

對內容套用項目捲動效果
常見用途是使用捲動位置,將效果套用至分頁檢視器項目。如要瞭解某個頁面與目前所選頁面的距離,可以使用 PagerState.currentPageOffsetFraction
。然後,您可以根據與所選頁面的距離,對內容套用變形效果。
舉例來說,如要根據項目與中心的距離調整不透明度,請使用 Modifier.graphicsLayer
變更分頁器內項目的 alpha
:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager(state = pagerState) { page -> Card( Modifier .size(200.dp) .graphicsLayer { // Calculate the absolute offset for the current page from the // scroll position. We use the absolute value which allows us to mirror // any effects for both directions val pageOffset = ( (pagerState.currentPage - page) + pagerState .currentPageOffsetFraction ).absoluteValue // We animate the alpha, between 50% and 100% alpha = lerp( start = 0.5f, stop = 1f, fraction = 1f - pageOffset.coerceIn(0f, 1f) ) } ) { // Card content } }
自訂頁面大小
根據預設,HorizontalPager
和 VerticalPager
分別會佔用完整寬度或完整高度。您可以將 pageSize
變數設為 Fixed
、Fill
(預設) 或自訂大小計算。
舉例來說,如要將頁面寬度設為固定值 100.dp
,請按照下列步驟操作:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(100.dp) ) { page -> // page content }
如要根據可視區域大小調整網頁大小,請使用自訂網頁大小計算。建立自訂
PageSize
物件,並將 availableSpace
除以三,同時考量項目之間的間距:
private val threePagesPerViewport = object : PageSize { override fun Density.calculateMainAxisPageSize( availableSpace: Int, pageSpacing: Int ): Int { return (availableSpace - 2 * pageSpacing) / 3 } }
內容間距
HorizontalPager
和 VerticalPager
都支援變更內容邊框間距,可讓您影響網頁的最大尺寸和對齊方式。
舉例來說,設定 start
邊框間距會將頁面靠向結尾對齊:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(start = 64.dp), ) { page -> // page content }
將 start
和 end
邊框間距設為相同的值,即可將項目水平置中:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(horizontal = 32.dp), ) { page -> // page content }
設定 end
邊框間距可將頁面靠向開頭對齊:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(end = 64.dp), ) { page -> // page content }
您可以設定 top
和 bottom
值,為 VerticalPager
達到類似效果。這裡僅以 32.dp
值為例,您可以將每個邊框間距維度設為任何值。
自訂捲動行為
預設的 HorizontalPager
和 VerticalPager
可組合項會指定捲動手勢如何與分頁檢視區塊搭配運作。不過,您可以自訂及變更預設值,例如 pagerSnapDistance
或 flingBehavior
。
貼齊距離
根據預設,HorizontalPager
和 VerticalPager
會將輕拂手勢可捲動的頁面數上限設為一次一頁。如要變更這項設定,請在 flingBehavior
上設定 pagerSnapDistance
:
val pagerState = rememberPagerState(pageCount = { 10 }) val fling = PagerDefaults.flingBehavior( state = pagerState, pagerSnapDistance = PagerSnapDistance.atMost(10) ) Column(modifier = Modifier.fillMaxSize()) { HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(200.dp), beyondViewportPageCount = 10, flingBehavior = fling ) { PagerSampleItem(page = it) } }
建立自動換頁的呼叫器
本節說明如何在 Compose 中建立自動捲動的分頁器,並顯示頁面指標。系統會自動水平捲動項目集合,但使用者也可以手動滑動切換項目。如果使用者與分頁器互動,自動進度就會停止。
基本範例
下列程式碼片段會共同建立基本的自動前進分頁器實作項目,並提供視覺指標,其中每個頁面都會以不同顏色呈現:
@Composable fun AutoAdvancePager(pageItems: List<Color>, modifier: Modifier = Modifier) { Box(modifier = Modifier.fillMaxSize()) { val pagerState = rememberPagerState(pageCount = { pageItems.size }) val pagerIsDragged by pagerState.interactionSource.collectIsDraggedAsState() val pageInteractionSource = remember { MutableInteractionSource() } val pageIsPressed by pageInteractionSource.collectIsPressedAsState() // Stop auto-advancing when pager is dragged or one of the pages is pressed val autoAdvance = !pagerIsDragged && !pageIsPressed if (autoAdvance) { LaunchedEffect(pagerState, pageInteractionSource) { while (true) { delay(2000) val nextPage = (pagerState.currentPage + 1) % pageItems.size pagerState.animateScrollToPage(nextPage) } } } HorizontalPager( state = pagerState ) { page -> Text( text = "Page: $page", textAlign = TextAlign.Center, modifier = modifier .fillMaxSize() .background(pageItems[page]) .clickable( interactionSource = pageInteractionSource, indication = LocalIndication.current ) { // Handle page click } .wrapContentSize(align = Alignment.Center) ) } PagerIndicator(pageItems.size, pagerState.currentPage) } }
程式碼重點
AutoAdvancePager
函式會建立具有自動前進功能的水平分頁檢視畫面。這個函式會將Color
物件清單做為輸入內容,這些物件會做為每個頁面的背景顏色。pagerState
是使用rememberPagerState
建立,用於保存分頁檢視區塊的狀態。pagerIsDragged
和pageIsPressed
追蹤使用者互動。- 除非使用者拖曳分頁器或按下其中一個頁面,否則
LaunchedEffect
會每兩秒自動前進分頁器。 HorizontalPager
會顯示網頁清單,每個網頁都有Text
可組合項,顯示網頁編號。這個修飾符會填滿頁面、從pageItems
設定背景顏色,並讓頁面可供點選。
@Composable fun PagerIndicator(pageCount: Int, currentPageIndex: Int, modifier: Modifier = Modifier) { Box(modifier = Modifier.fillMaxSize()) { Row( modifier = Modifier .wrapContentHeight() .fillMaxWidth() .align(Alignment.BottomCenter) .padding(bottom = 8.dp), horizontalArrangement = Arrangement.Center ) { repeat(pageCount) { iteration -> val color = if (currentPageIndex == iteration) Color.DarkGray else Color.LightGray Box( modifier = modifier .padding(2.dp) .clip(CircleShape) .background(color) .size(16.dp) ) } } } }
程式碼重點
Box
可組合函式會做為根元素。- 在
Box
內,Row
可組合函式會以水平方式排列頁面指標。
- 在
- 自訂頁面指標會顯示為一列圓圈,其中每個
Box
都會裁剪為circle
,代表一個頁面。 - 目前頁面的圓圈會以
DarkGray
著色,其他圓圈則為LightGray
。currentPageIndex
參數會決定要以深灰色顯示哪個圓圈。
結果
這部影片會顯示上述程式碼片段的基本自動前進分頁器: