Compose'da Pager

İçerikleri soldan sağa veya yukarıdan aşağıya çevirmek için sırasıyla HorizontalPager ve VerticalPager bileşenlerini kullanabilirsiniz. Bu bileşenler, görüntüleme sistemindeki ViewPager ile benzer işlevlere sahiptir. Varsayılan olarak HorizontalPager ekranın tüm genişliğini, VerticalPager ise tüm yüksekliğini kaplar ve sayfalayıcılar yalnızca bir sayfayı aynı anda gösterir. Bu varsayılanların tümü yapılandırılabilir.

HorizontalPager

Sola ve sağa yatay olarak kaydıran bir sayfalayıcı oluşturmak için HorizontalPagerşunları kullanın:

Şekil 1. HorizontalPager
demosu

// 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ğı kaydıran bir sayfalayıcı oluşturmak için VerticalPager simgesini kullanın:

Şekil 2. VerticalPager demosu

// Display 10 items
val pagerState = rememberPagerState(pageCount = {
    10
})
VerticalPager(state = pagerState) { page ->
    // Our page content
    Text(
        text = "Page: $page",
        modifier = Modifier.fillMaxWidth()
    )
}

Tembel oluşturma

Hem HorizontalPager hem de VerticalPager'teki sayfalar, gerektiğinde tembel bir şekilde derlenir ve düzenlenir. Kullanıcı olarak sayfalar arasında gezindiğinde composable, artık güncelliğini yitirmiş gereklidir.

Ekran dışında daha fazla sayfa yükle

Varsayılan olarak, çağrı cihazı yalnızca ekranda görünen sayfaları yükler. Ekran dışında daha fazla sayfa yüklemek için beyondBoundsPageCount öğesini 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 rememberPagerState() kullanarak bir PagerState nesnesi oluşturun ve bunu sayfalayıcıya state parametresi olarak iletin. Şu numarayı arayabilirsiniz: PagerState#scrollToPage() bu eyalette, bir CoroutineScope içinde:

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, sayfalarla ilgili bilgiler içeren üç özelliğe sahiptir: currentPage, settledPage ve targetPage.

  • currentPage: Tutturma konumuna en yakın sayfa. Varsayılan olarak, düzenin başında yer alır.
  • settledPage: Animasyon veya kaydırma yapılmadığında gösterilen sayfa numarası. Bu, sayfa sabitleme konumuna yeterince yakınsa currentPage hemen güncellenir ancak settledPage tüm animasyonlar tamamlanana kadar aynı kalır. Bu nedenle, currentPage mülkünden farklıdır.
  • targetPage: Kaydırma hareketi için önerilen durak konumu.

Bu değişkenlerdeki değişiklikleri gözlemlemek için snapshotFlow işlevini kullanabilirsiniz yanıt verebilirler. Örneğin, her sayfa değişimiyle ilgili 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 bilgi alın ve sayfa sayısı arasından hangi sayfanın seçildiğini belirleyin ve özel göstergesidir.

Örneğin, basit bir daire göstergesi istiyorsanız aynı öğenin sayısını tekrarlayabilirsiniz. daire içine alın ve sayfanın seçili olup olmadığına bağlı olarak daire rengini değiştirin 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)
        )
    }
}

İçeriğin altında daire göstergesi gösteren sayfalayıcı
Şekil 3. İçeriğin altında bir daire göstergesi gösteren çağrı cihazı
'nı inceleyin.

İçeriğe öğe kaydırma efektleri uygulama

Yaygın kullanım alanlarından biri, çağrı cihazınıza efektler uygulamak için kaydırma konumunu kullanmaktır öğeler. Bir sayfanın, seçili sayfaya ne kadar uzak olduğunu öğrenmek için PagerState.currentPageOffsetFraction simgesini kullanabilirsiniz. Ardından, mesafeye göre içeriklerinize dönüştürme efektleri uygulayabilirsiniz (seçilen sayfadan).

Şekil 4. Sayfalayıcı içeriğine dönüşüm uygulama

Örneğin, öğelerin opaklıklarını Center'ı kullanarak alpha öğesini değiştirin Modifier.graphicsLayer kodunu ekleyin:

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 tam genişliği kaplar veya tam yükseklikte. pageSize değişkenini Fixed, Fill (varsayılan) veya özel boyut hesaplaması.

Örneğin, 100.dp sabit genişliğinde 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 kullanın hesaplamanız gerekir. Özel oluştur PageSize nesnesini tanımlayın ve availableSpace değerini, boşluk bırakmaya dikkat ederek üçe bölün şunları içerir:

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

İçerik doldurma

Hem HorizontalPager hem de VerticalPager, içerik dolgusunun değiştirilmesini destekler. Bu sayede sayfaların maksimum boyutunu ve hizalamasını etkileyebilirsiniz.

Örneğin, start dolgusunu ayarlamak sayfaları sona doğru hizalar:

İçeriği sona doğru hizalanmış olarak gösteren başlangıç dolgusu içeren sayfalayıcı

val pagerState = rememberPagerState(pageCount = {
    4
})
HorizontalPager(
    state = pagerState,
    contentPadding = PaddingValues(start = 64.dp),
) { page ->
    // page content
}

Hem start hem de end dolgusu aynı değere ayarlanırsa öğe ortalanır yatay olarak:

İçeriği ortada gösteren başlangıç ve bitiş dolgusu içeren sayfalayıcı

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:

İçeriği başa hizalı olarak gösteren başlangıç ve bitiş dolgulu sayfa cihazı

val pagerState = rememberPagerState(pageCount = {
    4
})
HorizontalPager(
    state = pagerState,
    contentPadding = PaddingValues(end = 64.dp),
) { page ->
    // page content
}

VerticalPager için benzer efektler elde etmek üzere top ve bottom değerlerini ayarlayabilirsiniz. 32.dp değeri yalnızca burada örnek olarak kullanılmıştır. bu bilgiyi Dolgu boyutlarının her birini herhangi bir değere ayarlayabilirsiniz.

Kaydırma davranışını özelleştirme

Varsayılan HorizontalPager ve VerticalPager bileşenleri, kaydırma hareketlerinin sayfalayıcıyla nasıl çalıştığını belirtir. Ancak, mevcut metin reklamlarınızı pagerSnapDistance veya flingBehavior gibi varsayılan değerleri kullanabilirsiniz.

Kırpma mesafesi

Varsayılan olarak HorizontalPager ve VerticalPager, maksimum Kaydırma hareketinin tek seferde bir sayfaya ilerleyebileceği sayfalar. Bunu değiştirmek için flingBehavior'te pagerSnapDistance değerini 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)
    }
}