コンテンツを左右または上下にめくるには、それぞれ HorizontalPager
と VerticalPager
コンポーザブルを使用します。これらのコンポーザブルは、ビューシステムの ViewPager
と同様の機能を持ちます。デフォルトでは、HorizontalPager
は画面の幅全体を占有し、VerticalPager
は高さ全体を占有し、ページャーは一度に 1 ページのみをフリングします。これらのデフォルトはすべて構成可能です。
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
を使用します。
// 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
を 0 より大きい値に設定します。
ページャー内のアイテムまでスクロールする
ページャー内の特定のページにスクロールするには、rememberPagerState()
を使用して PagerState
オブジェクトを作成し、state
パラメータとしてページャーに渡します。この状態の CoroutineScope
内で PagerState#scrollToPage()
を呼び出すことができます。
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) ) } }
コンテンツにアイテムのスクロール効果を適用する
一般的なユースケースとして、スクロール位置を使用してページャー アイテムにエフェクトを適用することがあります。ページが現在選択されているページからどのくらい離れているかを確認するには、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
を 3 で割ります。
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
は、スワイプ操作で一度にスクロールできるページの最大数を 1 ページに設定します。これを変更するには、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) } }
あなたへのおすすめ
- 注: JavaScript がオフになっている場合はリンクテキストが表示されます
- Compose の ConstraintLayout
- グラフィック修飾子
CoordinatorLayout
を Compose に移行する