Pager w sekcji Utwórz

Do przełączania treści w lewo i w prawo lub w górę i w dół możesz używać HorizontalPager oraz VerticalPager elementów kompozycyjnych. Te elementy kompozycyjne mają podobne funkcje ViewPager w widoku systemu. Domyślnie HorizontalPager zajmuje całą szerokość ekranu, VerticalPager zajmuje całą wysokość, a pagery pomijają tylko jedną stronę. obecnie się znajdujesz. Wszystkie te wartości domyślne możesz skonfigurować.

HorizontalPager

Aby utworzyć pager, który przewija się w poziomie w lewo i w prawo, użyj HorizontalPager:

Rysunek 1. Wersja demonstracyjna: HorizontalPager

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

VerticalPager

Aby utworzyć pager, który przewija się w górę i w dół, użyj elementu VerticalPager:

Rysunek 2. Wersja demonstracyjna: VerticalPager

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

Tworzenie bezmyślne

Strony w językach: HorizontalPager i VerticalPager działają leniwie skomponowane i rozmieszczone w razie potrzeby. Jako użytkownik przewija strony, funkcja kompozycyjna usuwa wszystkie strony, które już nie są

Wczytywanie większej liczby stron poza ekranem

Domyślnie pager wczytuje tylko strony widoczne na ekranie. Aby wczytać więcej stron poza ekranem, ustaw beyondBoundsPageCount na wartość większą niż 0.

Przewiń do elementu na stronie pagera

Aby przewinąć do określonej strony na stronie, utwórz PagerState za pomocą rememberPagerState() i przekazać go do pagera jako parametr state. Możesz zadzwonić do nas, PagerState#scrollToPage() w tym stanie, w elemencie 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")
}

Jeśli chcesz użyć animacji na stronie, użyj funkcji 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")
}

Otrzymywanie powiadomień o zmianach stanu strony

PagerState ma 3 właściwości z informacjami o stronach: currentPage, settledPage, oraz targetPage.

  • currentPage: strona, która znajduje się najbliższa położeniemu przyciągania. Domyślnie przyciąganie znajduje się na początku układu.
  • settledPage: numer strony, gdy nie jest uruchomiona żadna animacja ani przewijanie. Ten różni się od właściwości currentPage tym, że currentPage natychmiast aktualizuje się, gdy strona jest wystarczająco blisko miejsca przyciągania, ale Wartość settledPage pozostaje bez zmian, dopóki wszystkie animacje nie zostaną zakończone.
  • targetPage: proponowana pozycja zatrzymania przewijania.

Za pomocą funkcji snapshotFlow możesz obserwować zmiany tych zmiennych i na nie reagować. Aby np. wysyłać zdarzenie analityczne przy każdej zmianie strony, możesz wykonać te czynności:

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")
}

Dodaj wskaźnik strony

Aby dodać wskaźnik do strony, użyj obiektu PagerState do uzyskania informacji na temat tego, która strona jest wybrana z liczby stron, i narysuj własny wskaźnik.

Na przykład jeśli chcesz używać prostego wskaźnika okręgu, możesz powtórzyć liczbę i zmień ich kolor w zależności od tego, czy wybrana jest strona 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)
        )
    }
}

Strony przewijania z wskaźnikiem w kształcie koła pod treścią
Rysunek 3. Pager z ikoną koła pod treścią

Zastosuj efekty przewijania elementów do treści

Typowym przypadkiem użycia jest użycie pozycji przewijania do zastosowania efektów do pagera. elementy(ów). Aby dowiedzieć się, jak daleko od wybranej strony znajduje się strona, możesz należy użyć funkcji PagerState.currentPageOffsetFraction Następnie możesz zastosować efekty przekształceniowe do treści dostosowane do odległości z wybranej strony.

Rysunek 4. Zastosowanie przekształceń do treści pagera

Aby na przykład dostosować przezroczystość elementów na podstawie ich odległości od obrazu w środku, zmień alpha za pomocą Modifier.graphicsLayer. na elemencie na stronie pagera:

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
    }
}

Niestandardowe rozmiary stron

Domyślnie HorizontalPager i VerticalPager zajmują pełną szerokość lub pełnej wysokości. Zmienną pageSize możesz ustawić tak, aby miała wartość Fixed, Fill (domyślnie) lub niestandardowe obliczenie rozmiaru.

Aby na przykład ustawić stronę o stałej szerokości strony 100.dp:

val pagerState = rememberPagerState(pageCount = {
    4
})
HorizontalPager(
    state = pagerState,
    pageSize = PageSize.Fixed(100.dp)
) { page ->
    // page content
}

Aby zmienić rozmiar strony na podstawie rozmiaru widocznego obszaru, użyj niestandardowego rozmiaru strony obliczeń. Utwórz niestandardową PageSize i podziel availableSpace przez trzy, biorąc pod uwagę odstępy między elementami:

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

wypełnienie treści;

Zarówno HorizontalPager, jak i VerticalPager obsługują zmianę wypełnienia treści, co pozwala wpływać na maksymalny rozmiar i wyrównanie stron.

Na przykład ustawienie dopełnienia start spowoduje wyrównanie strony do końca:

Stronka z wypełnieniem na początku, na której treść jest wyrównana do końca

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

Ustawienie dopełnienia start i end ma taką samą wartość, względem którego wyśrodkowuje się element w poziomie:

Pager z dopełnieniem na początku i na końcu przedstawiającym treść wyśrodkowaną

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

Ustawienie wypełnienia end wyrównuje strony do początku:

Pager z dopełnieniem początkowym i końcowym przedstawiającym treść wyrównaną do początku

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

Aby uzyskać podobne efekty, możesz ustawić wartości top i bottom. VerticalPager Wartość 32.dp jest tu używana tylko do celów poglądowych. Każdy z wymiarów wypełniania możesz ustawić na dowolną wartość.

Dostosowywanie działania przewijania

Domyślne komponenty HorizontalPagerVerticalPager określają, jak gesty przewijania działają w przypadku strony. Możesz jednak dostosować i zmienić wartości domyślne, takie jak pagerSnapDistance lub flingBehavior.

Odległość przyciągania

Domyślnie HorizontalPagerVerticalPager określają maksymalną liczbę stron, które gest przesuwania może przewinąć o jedną stronę naraz. Aby zmienić to, ustaw pagerSnapDistanceflingBehavior:

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)
    }
}