İçeriklerde sırasıyla sola ve sağa ya da yukarı ve aşağı kaydırmak için HorizontalPager
ve VerticalPager
composable'larını kullanabilirsiniz. Bu composables, görünüm sistemindeki ViewPager
ile benzer işlevlere sahiptir. Varsayılan olarak HorizontalPager
ekranın tam genişliğini, VerticalPager
ise tam yüksekliğini kaplar ve sayfalayıcılar yalnızca bir sayfayı bir kerede kaydırır. Bu varsayılanların tümü yapılandırılabilir.
HorizontalPager
Yatay olarak sola ve sağa kayan bir sayfalayıcı oluşturmak için HorizontalPager
öğesini kullanın:
HorizontalPager
demosunu izleyin
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) HorizontalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
VerticalPager
Yukarı ve aşağı kayan bir sayfalayıcı oluşturmak için VerticalPager
kullanın:
VerticalPager
demosunu izleyin
// Display 10 items val pagerState = rememberPagerState(pageCount = { 10 }) VerticalPager(state = pagerState) { page -> // Our page content Text( text = "Page: $page", modifier = Modifier.fillMaxWidth() ) }
Geç oluşturma
Hem HorizontalPager
hem de VerticalPager
içindeki sayfalar geç oluşturulur ve gerektiğinde düzenlenir. Kullanıcı sayfalar arasında kaydırma yaparken composable, artık gerekli olmayan sayfaları kaldırır.
Ekran dışında daha fazla sayfa yükleme
Varsayılan olarak, sayfalayıcı yalnızca ekranda görünen sayfaları yükler. Ekran dışında daha fazla sayfa yüklemek için beyondBoundsPageCount
değerini sıfırdan büyük bir değere ayarlayın.
Sayfalayıcıda bir öğeye kaydırma
Sayfalama aracında belirli bir sayfaya gitmek için rememberPagerState()
kullanarak bir PagerState
nesnesi oluşturun ve bunu sayfalama aracına state
parametresi olarak iletin. Bu durumda, PagerState#scrollToPage()
adlı işlevi CoroutineScope
içinde şu şekilde çağırabilirsiniz:
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") }
Sayfayı animasyonla göstermek istiyorsanız PagerState#animateScrollToPage()
işlevini kullanın:
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") }
Sayfa durumu değişiklikleri hakkında bildirim alma
PagerState
sayfalarla ilgili bilgileri içeren üç özelliğe sahiptir:
currentPage
,
settledPage
ve
targetPage
.
currentPage
: Sabitleme konumuna en yakın sayfa. Varsayılan olarak, tutturma konumu düzenin başlangıcındadır.settledPage
: Animasyon veya kaydırma işlemi çalışmadığında sayfa numarası. Bu,currentPage
özelliğinden farklıdır.currentPage
, sayfa tutturma konumuna yeterince yakınsa hemen güncellenir ancaksettledPage
, tüm animasyonlar çalışmayı bitirene kadar aynı kalır.targetPage
: Kaydırma hareketi için önerilen durdurma konumu.
Bu değişkenlerdeki değişiklikleri gözlemlemek ve bunlara tepki vermek için snapshotFlow
işlevini kullanabilirsiniz. Örneğin, her sayfa değişikliğinde bir Analytics etkinliği göndermek için şunları yapabilirsiniz:
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") }
Sayfa göstergesi ekleme
Bir sayfaya gösterge eklemek için PagerState
nesnesini kullanarak sayfa sayısı arasından hangi sayfanın seçildiği hakkında bilgi edinin ve özel göstergenizi çizin.
Örneğin, basit bir daire göstergesi istiyorsanız daire sayısını tekrarlayabilir ve pagerState.currentPage
kullanarak sayfanın seçilip seçilmediğine bağlı olarak daire rengini değiştirebilirsiniz:
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) ) } }

İçeriğe öğe kaydırma efektleri uygulama
Yaygın bir kullanım alanı, kaydırma konumunu kullanarak sayfalama öğelerinize efekt uygulamaktır. Bir sayfanın, şu anda seçili olan sayfadan ne kadar uzakta olduğunu öğrenmek için PagerState.currentPageOffsetFraction
simgesini kullanabilirsiniz.
Ardından, seçilen sayfaya olan mesafeye göre içeriğinize dönüştürme efektleri uygulayabilirsiniz.
Örneğin, öğelerin opaklığını merkezden ne kadar uzakta olduklarına göre ayarlamak için sayfalayıcıdaki bir öğede Modifier.graphicsLayer
kullanarak alpha
değerini değiştirin:
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 } }
Özel sayfa boyutları
Varsayılan olarak HorizontalPager
ve VerticalPager
sırasıyla tam genişliği veya tam yüksekliği kaplar. pageSize
değişkenini Fixed
, Fill
(varsayılan) veya özel bir boyut hesaplaması olarak ayarlayabilirsiniz.
Örneğin, 100.dp
genişliğinde sabit bir sayfa ayarlamak için:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, pageSize = PageSize.Fixed(100.dp) ) { page -> // page content }
Sayfaları görüntü alanı boyutuna göre boyutlandırmak için özel bir sayfa boyutu hesaplaması kullanın. Özel bir PageSize
oluşturun ve öğeler arasındaki boşluğu dikkate alarak availableSpace
öğesini üçe bölün:
private val threePagesPerViewport = object : PageSize { override fun Density.calculateMainAxisPageSize( availableSpace: Int, pageSpacing: Int ): Int { return (availableSpace - 2 * pageSpacing) / 3 } }
İçerik dolgusu
HorizontalPager
ve VerticalPager
, içerik dolgusunun değiştirilmesini destekler. Bu sayede sayfaların maksimum boyutunu ve hizalamasını etkileyebilirsiniz.
Örneğin, start
dolgusunun ayarlanması sayfaları sona doğru hizalar:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(start = 64.dp), ) { page -> // page content }
Hem start
hem de end
dolgusunu aynı değere ayarlamak öğeyi yatay olarak ortalar:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(horizontal = 32.dp), ) { page -> // page content }
end
dolgusunu ayarlamak sayfaları başlangıca doğru hizalar:
val pagerState = rememberPagerState(pageCount = { 4 }) HorizontalPager( state = pagerState, contentPadding = PaddingValues(end = 64.dp), ) { page -> // page content }
top
ve bottom
değerlerini ayarlayarak VerticalPager
için benzer efektler elde edebilirsiniz. 32.dp
değeri burada yalnızca örnek olarak kullanılmıştır. Dolgu boyutlarının her birini istediğiniz değere ayarlayabilirsiniz.
Kaydırma davranışını özelleştirme
Varsayılan HorizontalPager
ve VerticalPager
composable'ları, kaydırma hareketlerinin sayfalayıcıyla nasıl çalıştığını belirtir. Ancak pagerSnapDistance
veya flingBehavior
gibi varsayılanları özelleştirebilir ve değiştirebilirsiniz.
Tutturma mesafesi
Varsayılan olarak, HorizontalPager
ve VerticalPager
, bir kaydırma hareketinin kaydırabileceği maksimum sayfa sayısını her seferinde bir sayfa olarak ayarlar. Bunu değiştirmek için flingBehavior
üzerinde pagerSnapDistance
ayarını yapın:
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) } }
Otomatik ilerleyen sayfalayıcı oluşturma
Bu bölümde, Compose'da sayfa göstergeleri içeren otomatik ilerleyen bir sayfalayıcı oluşturma işlemi açıklanmaktadır. Öğeler koleksiyonu otomatik olarak yatay kaydırılır ancak kullanıcılar öğeler arasında manuel olarak da kaydırabilir. Kullanıcı, sayfalayıcıyla etkileşim kurarsa otomatik ilerleme durdurulur.
Temel örnek
Aşağıdaki snippet'ler birlikte, her sayfanın farklı bir renkte oluşturulduğu, görsel göstergeli temel bir otomatik ilerleyen sayfalayıcı uygulaması oluşturur:
@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) } }
Kodla ilgili önemli noktalar
AutoAdvancePager
işlevi, otomatik ilerlemeyle yatay olarak sayfalandırılan bir görünüm oluşturur. Her sayfanın arka plan rengi olarak kullanılanColor
nesnelerinin listesini giriş olarak alır.pagerState
, sayfalayıcının durumunu tutanrememberPagerState
kullanılarak oluşturulur.pagerIsDragged
vepageIsPressed
kullanıcı etkileşimini izler.- Kullanıcı, sayfalayı sürüklemediği veya sayfalardan birine basmadığı sürece
LaunchedEffect
, sayfalandırıcıyı iki saniyede bir otomatik olarak ilerletir. HorizontalPager
, her biri sayfa numarasını gösterenText
composable'ı içeren bir sayfa listesi gösterir. Değiştirici, sayfayı doldurur, arka plan renginipageItems
olarak ayarlar ve sayfayı tıklanabilir hale getirir.
@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) ) } } } }
Kodla ilgili önemli noktalar
- Kök öğe olarak
Box
composable'ı kullanılır.Box
içinde,Row
composable'ı, sayfa göstergelerini yatay olarak düzenler.
- Özel sayfa göstergesi, bir daireler satırı olarak gösterilir.
Box
Hercircle
, bir sayfayı temsil eder. - Geçerli sayfanın dairesi
DarkGray
renginde, diğer daireler iseLightGray
rengindedir.currentPageIndex
parametresi, hangi dairenin koyu gri renkte oluşturulacağını belirler.
Sonuç
Bu videoda, önceki snippet'lerdeki temel otomatik ilerleyen sayfalayıcı gösterilmektedir: