Untuk membalik konten secara kiri dan kanan atau atas dan bawah, Anda dapat menggunakan
composable
HorizontalPager
dan
VerticalPager
. Composable ini memiliki fungsi yang serupa dengan
ViewPager
dalam sistem
tampilan. Secara default, HorizontalPager
menggunakan lebar layar penuh,
VerticalPager
menggunakan tinggi penuh, dan penggeser hanya menggeser satu halaman dalam satu
waktu. Semua default ini dapat dikonfigurasi.
HorizontalPager
Untuk membuat penomoran halaman yang men-scroll secara horizontal ke kiri dan kanan, gunakan
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
Untuk membuat penomoran halaman yang men-scroll ke atas dan ke bawah, gunakan VerticalPager
:
VerticalPager
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
Pembuatan lambat
Halaman di HorizontalPager
dan VerticalPager
dikomposisikan
secara lambat dan ditata saat diperlukan. Saat pengguna
men-scroll halaman, composable akan menghapus halaman yang tidak lagi
diperlukan.
Memuat halaman lainnya di luar layar
Secara default, penomoran halaman hanya memuat halaman yang terlihat di layar. Untuk memuat lebih banyak halaman di luar layar, tetapkan beyondBoundsPageCount
ke nilai yang lebih tinggi dari nol.
Men-scroll ke item di penomoran halaman
Untuk men-scroll ke halaman tertentu di pager, buat objek
PagerState
menggunakan
rememberPagerState()
dan teruskan sebagai parameter state
ke pager. Anda dapat memanggil
PagerState#scrollToPage()
pada status ini, di dalam 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") }
Jika Anda ingin menganimasikan ke halaman, gunakan fungsi
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") }
Mendapatkan notifikasi tentang perubahan status halaman
PagerState
memiliki tiga properti dengan informasi tentang halaman:
currentPage
,
settledPage
,
dan
targetPage
.
currentPage
: Halaman terdekat dengan posisi pengepasan. Secara default, posisi penyambungan berada di awal tata letak.settledPage
: Nomor halaman saat tidak ada animasi atau scrolling yang berjalan. Hal ini berbeda dengan properticurrentPage
karenacurrentPage
langsung diperbarui jika halaman cukup dekat dengan posisi penarikan, tetapisettledPage
tetap sama hingga semua animasi selesai berjalan.targetPage
: Posisi berhenti yang diusulkan untuk gerakan men-scroll.
Anda dapat menggunakan fungsi snapshotFlow
untuk mengamati perubahan pada variabel ini dan bereaksi terhadapnya. Misalnya, untuk mengirim peristiwa analisis pada setiap perubahan halaman,
Anda dapat melakukan hal berikut:
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") }
Menambahkan indikator halaman
Untuk menambahkan indikator ke halaman, gunakan objek PagerState
untuk mendapatkan informasi tentang halaman mana yang dipilih dari sejumlah halaman, dan gambar indikator kustom Anda.
Misalnya, jika Anda menginginkan indikator lingkaran sederhana, Anda dapat mengulangi jumlah
lingkaran dan mengubah warna lingkaran berdasarkan apakah halaman dipilih, menggunakan
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) ) } }

Menerapkan efek scroll item ke konten
Kasus penggunaan umum adalah menggunakan posisi scroll untuk menerapkan efek ke item pager Anda. Untuk mengetahui seberapa jauh halaman dari halaman yang saat ini dipilih, Anda dapat menggunakan
PagerState.currentPageOffsetFraction
.
Kemudian, Anda dapat menerapkan efek transformasi ke konten berdasarkan jarak dari halaman yang dipilih.
Misalnya, untuk menyesuaikan keburaman item berdasarkan seberapa jauh item tersebut dari
tengah, ubah alpha
menggunakan
Modifier.graphicsLayer
pada item di dalam pager:
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 } }
Ukuran halaman kustom
Secara default, HorizontalPager
dan VerticalPager
masing-masing menggunakan lebar penuh atau tinggi penuh. Anda dapat menetapkan variabel pageSize
agar memiliki
Fixed
,
Fill
(default), atau penghitungan ukuran kustom.
Misalnya, untuk menetapkan halaman lebar tetap 100.dp
:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(100.dp) ) { page -> // page content }
Untuk menentukan ukuran halaman berdasarkan ukuran area pandang, gunakan perhitungan ukuran halaman kustom. Buat objek
PageSize
kustom dan bagi availableSpace
dengan tiga, dengan mempertimbangkan jarak
antar-item:
private val threePagesPerViewport = object : PageSize { override fun Density.calculateMainAxisPageSize( availableSpace: Int, pageSpacing: Int ): Int { return (availableSpace - 2 * pageSpacing) / 3 } }
Padding konten
HorizontalPager
dan VerticalPager
mendukung perubahan padding konten,
yang memungkinkan Anda memengaruhi ukuran dan perataan maksimum halaman.
Misalnya, menyetel padding start
akan menyelaraskan halaman ke arah akhir:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(start = 64.dp), ) { page -> // page content }
Menetapkan padding start
dan end
ke nilai yang sama akan memusatkan item secara horizontal:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(horizontal = 32.dp), ) { page -> // page content }
Menyetel padding end
akan menyelaraskan halaman ke arah awal:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(end = 64.dp), ) { page -> // page content }
Anda dapat menetapkan nilai top
dan bottom
untuk mendapatkan efek serupa untuk
VerticalPager
. Nilai 32.dp
hanya digunakan di sini sebagai contoh; Anda dapat menetapkan
setiap dimensi padding ke nilai apa pun.
Menyesuaikan perilaku scroll
Composable HorizontalPager
dan VerticalPager
default menentukan cara
gestur men-scroll berfungsi dengan pager. Namun, Anda dapat menyesuaikan dan mengubah
setelan default seperti pagerSnapDistance
atau flingBehavior
.
Jarak penempelan
Secara default, HorizontalPager
dan VerticalPager
menetapkan jumlah maksimum
halaman yang dapat di-scroll oleh gestur menggeser ke satu halaman dalam satu waktu. Untuk mengubahnya, tetapkan
pagerSnapDistance
di 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) } }
Membuat penomoran halaman yang otomatis berpindah
Bagian ini menjelaskan cara membuat pager yang maju otomatis dengan indikator halaman di Compose. Kumpulan item otomatis men-scroll secara horizontal, tetapi pengguna juga dapat menggeser item secara manual. Jika pengguna berinteraksi dengan penomoran halaman, progres otomatis akan berhenti.
Contoh dasar
Bersama-sama, cuplikan berikut membuat penerapan pager maju otomatis dasar dengan indikator visual, yang setiap halamannya dirender sebagai warna yang berbeda:
@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) } }
Poin penting tentang kode
- Fungsi
AutoAdvancePager
membuat tampilan penomoran halaman horizontal dengan peralihan otomatis. Fungsi ini mengambil daftar objekColor
sebagai input, yang digunakan sebagai warna latar belakang untuk setiap halaman. pagerState
dibuat menggunakanrememberPagerState
, yang menyimpan status pager.pagerIsDragged
danpageIsPressed
melacak interaksi pengguna.LaunchedEffect
otomatis memajukan penomoran halaman setiap dua detik, kecuali jika pengguna menarik penomoran halaman atau menekan salah satu halaman.HorizontalPager
menampilkan daftar halaman, yang masing-masing memiliki composableText
yang menampilkan nomor halaman. Pengubah mengisi halaman, menetapkan warna latar belakang daripageItems
, dan membuat halaman dapat diklik.
@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) ) } } } }
Poin penting tentang kode
- Composable
Box
digunakan sebagai elemen root.- Di dalam
Box
, composableRow
mengatur indikator halaman secara horizontal.
- Di dalam
- Indikator halaman kustom ditampilkan sebagai baris lingkaran, dengan setiap
Box
yang di-clip kecircle
merepresentasikan satu halaman. - Lingkaran halaman saat ini diberi warna
DarkGray
, sedangkan lingkaran lainnya berwarnaLightGray
. ParametercurrentPageIndex
menentukan lingkaran mana yang dirender dalam warna abu-abu tua.
Hasil
Video ini menampilkan penggeser maju otomatis dasar dari cuplikan sebelumnya: