Compose でのページャー

コンテンツを左右または上下にめくるには、 HorizontalPager および VerticalPager 作成することもできます。これらのコンポーザブルには、Terraform と ビュー内の ViewPager ありませんデフォルトでは、HorizontalPager は画面の幅いっぱいに表示されます。 VerticalPager は画面全体の高さを占め、ページャーは 1 ページしかスクロールしません。 あります。これらのデフォルトは構成可能です。

HorizontalPager

左右に水平方向にスクロールするページャーを作成するには、次のコマンドを使用します。 HorizontalPager:

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">をご覧ください。
図 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 を使用します。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">をご覧ください。
図 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 を 0 より大きい値に設定します。

ページング内のアイテムまでスクロール

ページャーの特定のページにスクロールするには、 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 には、ページに関する情報を含む 3 つのプロパティがあります。 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。 移動距離に基づいてコンテンツに変換効果を適用できる クリックします

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">をご覧ください。
図 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 を 3 で割ります。 次のように分かれています

private val threePagesPerViewport = object : PageSize {
    override fun Density.calculateMainAxisPageSize(
        availableSpace: Int,
        pageSpacing: Int
    ): Int {
        return (availableSpace - 2 * pageSpacing) / 3
    }
}

コンテンツのパディング

HorizontalPagerVerticalPager はどちらもコンテンツのパディングの変更をサポートしています。 これにより、ページの最大サイズと配置を調整できます。

たとえば、パディング start を設定すると、ページは末端に配置されます。

コンテンツが末尾に揃えられた、開始パディング付きのページャー

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 の値を設定すると、次の場合に同様の効果が得られます。 VerticalPager。値 32.dp は、ここでは例としてのみ使用されます。[ パディングサイズを任意の値に変更できます。

スクロール動作をカスタマイズする

デフォルトの HorizontalPager コンポーザブルと VerticalPager コンポーザブルは、 ページャーと連動しますただし、Google Chat で pagerSnapDistanceflingBehavior などのデフォルト値を指定します。

スナップ距離

デフォルトでは、HorizontalPagerVerticalPager は、サービス アカウントの最大数を フリング操作で一度に 1 ページまでスクロールできるページ。変更する この 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),
        beyondBoundsPageCount = 10,
        flingBehavior = fling
    ) {
        PagerSampleItem(page = it)
    }
}