Compose 中的呼叫器

如要以左右或上下的方式瀏覽內容,可以使用 這個 HorizontalPager敬上 和 VerticalPager 可組合函式這些可組合函式具有類似的函式: 檢視畫面中有 ViewPager 有些人會將 Cloud Storage 視為檔案系統 但實際上不是根據預設,HorizontalPager 會佔據整個畫面的寬度, VerticalPager 佔滿整個高度,網頁工具 讓應用程式從可以最快做出回應的位置 回應使用者要求這些預設值都可以設定。

HorizontalPager

如要建立可水平左右捲動的分頁工具,請使用 HorizontalPager

圖 1.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

圖 2.「VerticalPager」示範

// Display 10 items
val pagerState = rememberPagerState(pageCount = {
    10
})
VerticalPager(state = pagerState) { page ->
    // Our page content
    Text(
        text = "Page: $page",
        modifier = Modifier.fillMaxWidth()
    )
}

延遲建立

HorizontalPagerVerticalPager 中的頁面會在需要時延遲組合和版面配置。身為使用者 捲動頁面時,可組合函式會移除不再的頁面 這通常代表交易 不會十分要求關聯語意

在螢幕外載入更多網頁

根據預設,網頁工具只會載入螢幕上的可見頁面。載入更多網頁 請將 beyondBoundsPageCount 設為大於零的值。

捲動至分頁器中的項目

如要在頁面工具中捲動至特定頁面,請建立 PagerState敬上 物件 rememberPagerState() 並將其做為 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)
        )
    }
}

在內容下方顯示圓形指標的頁面工具
圖 3. 在內容下方顯示圓形指標的頁面工具

將項目捲動效果套用至內容

常見的做法是使用捲動位置將效果套用至頁面控制項 項目。如果想瞭解頁面與目前所選頁面之間的距離 使用 PagerState.currentPageOffsetFraction。 接著可以根據距離,為內容套用變形效果 即可產生相應的文件

圖 4.將轉換套用至分頁內容

舉例來說,如果想根據項目距離某個區間的 置中,請使用以下指令變更 alpha Modifier.graphicsLayer

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
    }
}

自訂頁面大小

根據預設,HorizontalPagerVerticalPager 會採用整個寬度或 而這三個高度。您可以將 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
    }
}

內容間距

HorizontalPagerVerticalPager 都支援變更內容邊框間距, 來控制網頁的大小和對齊方式。

舉例來說,設定 start 邊框間距可將頁面靠近末端:

含起始邊框間距的 Pager,內容與結尾對齊

val pagerState = rememberPagerState(pageCount = {
    4
})
HorizontalPager(
    state = pagerState,
    contentPadding = PaddingValues(start = 64.dp),
) { page ->
    // page content
}

startend 邊框間距設為相同的值,即可將項目置中 水平:

使用開始和結束邊框間距的頁面控制項,顯示內容置中

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
}

您可以設定 topbottom 值來達成類似效果 VerticalPager32.dp 值只是在此範例使用;CANNOT TRANSLATE 將各個邊框間距維度對應到任何值

自訂捲動行為

預設的 HorizontalPagerVerticalPager 可組合函式會指定 捲動手勢可搭配頁面工具使用。不過,你可以自訂及變更 預設值,例如 pagerSnapDistanceflingBehavior

貼齊距離

根據預設,HorizontalPagerVerticalPager 所設定的數量上限 快速滑過手勢可以一次捲動至一個頁面的網頁。如要變更 設定目標 pagerSnapDistance敬上 在 flingBehavior

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)
    }
}