İçerikleri yatay veya dikey olarak kaydırmak için HorizontalPager ve VerticalPager composable'larını kullanabilirsiniz. Bu özellikler, görünüm sistemindeki ViewPager ile benzer işlevlere sahiptir. Varsayılan olarak,
HorizontalPager tam ekran genişliğini, VerticalPager ise tam ekran yüksekliğini kaplar. Ayrıca, çağrı cihazları da aynı anda yalnızca bir sayfa çevirir. Bu varsayılan değerlerin 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, gerektiğinde geç oluşturulur ve düzenlenir. Kullanıcı sayfalar arasında kaydırarak gezinirken 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
Sayfalayıcıda belirli bir sayfaya gitmek için PagerState nesnesi oluşturun
rememberPagerState() kullanarak ve bunu sayfalayıcıya state parametresi olarak iletin. Bu durumda, CoroutineScope içinde PagerState#scrollToPage() işlevini ç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") }
Sayfaya animasyon eklemek 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'da sayfalarla ilgili bilgilerin yer aldığı üç özellik bulunur: 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 analiz 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, daire göstergesi oluşturmak için daire sayısını tekrarlayabilir ve sayfanın seçilip seçilmediğine bağlı olarak daire rengini değiştirebilirsiniz. Bunun için pagerState.currentPage kullanın:
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 efektler uygulamaktır. Bir sayfanın seçili 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ı içerecek şekilde 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 nesnesi oluşturun ve öğeler arasındaki boşluğu dikkate alarak availableSpace değerini üç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 bölümünde pagerSnapDistance seçeneğini ayarlayı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 geçiş yapabilir. Kullanıcı kaydırma çubuğuyla etkileşimde bulunursa 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
AutoAdvancePagerişlevi, otomatik ilerlemeyle yatay olarak sayfalandırılan bir görünüm oluşturur. Her sayfanın arka plan rengi olarak kullanılanColornesnelerinin listesini giriş olarak alır.pagerState, sayfalayıcının durumunu tutanrememberPagerStatekullanılarak oluşturulur.pagerIsDraggedvepageIsPressed, 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 birinde sayfa numarasını gösterenTextcomposable'ın bulunduğu bir sayfa listesini gösterir. Değiştirici, sayfayı doldurur, arka plan renginipageItemsolarak 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
- Bir
Boxcomposable, kök öğe olarak işlev görür ve sayfa göstergelerini yatay olarak düzenlemek için birRowiçerir. - Özel sayfa göstergesi, bir daireler satırı olarak gösterilir.
BoxHerCircleShape, bir sayfayı temsil eder. - Geçerli sayfanın dairesi
DarkGrayrenginde, diğer daireler iseLightGrayrengindedir.currentPageIndexparametresi, hangi dairenin koyu gri renkte oluşturulacağını belirler.
Sonuç
Bu videoda, önceki snippet'lerdeki temel otomatik ilerleyen sayfalayıcı gösterilmektedir: