Пример пагинации. Навигационные кнопки

Последнее обновление: 10.04.2024

В прошлой статье были описаны общие моменты применения компонентов-пагинаторов VerticalPager и HorizontalPager. В этой статье рассмотрим примитивный пример применения постраничного вывода. В частности, определим следующее приложение:

package com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlin.random.Random

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent @OptIn(ExperimentalFoundationApi::class){
            // данные для отображения
            val data = listOf("iPhone 15 Pro", "Redmi Note 12 Pro+", "Galaxy S23 Ultra", "Infinix NOTE 30 Pro", "Honor 90")
            // состояние
            val pagerState = rememberPagerState { data.size }

            HorizontalPager(state = pagerState, Modifier.fillMaxHeight()) { page ->
                Column(Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally) {
                    val product = data[page]
                    Text(product, fontSize = 43.sp)
                    Box(Modifier
                        .fillMaxWidth(0.9f)
                        .fillMaxHeight(0.7f)
                        .padding(top=40.dp)
                        .background(
                            Color(
                                Random.nextInt(255),
                                Random.nextInt(255),
                                Random.nextInt(255),
                                255
                            )
                        )
                    )
                    Box(Modifier
                        .fillMaxWidth(0.9f)
                        .padding(top=20.dp)){
                        Text("Описание товара $product", fontSize = 28.sp)}
                }
            }
        }
    }
}

Здесь данные для отображения на страницах определены в виде списка data - списка мобильных устройств:

val data = listOf("iPhone 15 Pro", "Redmi Note 12 Pro+", "Galaxy S23 Ultra", "Infinix NOTE 30 Pro", "Honor 90")

Для каждого из элементов списка будет создаваться своя страница.

Создаем состояние PagerState, которое инициализируется количеством элементов списка (фактически количеством страниц):

val pagerState = rememberPagerState { data.size }

Далее определяем горизонтальный пагинатор HorizontalPager:

HorizontalPager(state = pagerState, Modifier.fillMaxHeight()) { page ->

Каждую страницу в пагинаторе фактически будет представлять столбец Column:

Column(Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally) {
    val product = data[page]
    Text(product, fontSize = 43.sp)
    Box(Modifier
        .fillMaxWidth(0.9f)
        .fillMaxHeight(0.7f)
        .padding(top=40.dp)
        .background(
            Color(Random.nextInt(255),Random.nextInt(255),Random.nextInt(255),255)
        )
    )
    Box(Modifier.fillMaxWidth(0.9f).padding(top=20.dp)){
        Text("Описание товара $product", fontSize = 28.sp)
    }
}

Страница может представлять любой компонент, содержать различные компоненты в зависимости от задачи приложения. Но в данном случае функционально страница разбивается на три части. В начале идет компонент Text с заголовком товара. Потом идет компонент Box, который принимает случайный цвет (здесь можно было бы вставить картинку, но, я думаю, для демонстрации сойдет и обычный Box). И под ним расположено описание товара в виде компонента Box со вложенным компонентом Text.

Таким образом, у нас получится следующий интерфейс страницы:

Пагинация в приложении на Jetpack Compose на Kotlin в Android

В итоге при запуске приложения мы сможем переходить к другим страницам с помощью прокручивания по горизонтали:

Постраничная навигация в мобильном приложении на Jetpack Compose на Kotlin в Android

Хотя здесь применяется горизонтальный пагинатор HorizontalPager, но аналогично можно было бы использовать и вертикальный пагинатор VerticalPager.

Кнопки навигации

Нередко для перемещения по страницам в приложениях применяются специальные кнопки навигации. Посмотрим, как их реализовать. Для этого определим следующее приложение:

package com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowLeft
import androidx.compose.material.icons.filled.KeyboardArrowRight
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch
import kotlin.random.Random

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent @OptIn(ExperimentalFoundationApi::class){
            val data = listOf("iPhone 15 Pro", "Redmi Note 12 Pro+", "Galaxy S23 Ultra", "Infinix NOTE 30 Pro", "Honor 90")
            val pagerState = rememberPagerState { data.size }
            val coroutineScope = rememberCoroutineScope()
            HorizontalPager(state = pagerState, Modifier.fillMaxHeight()) { page ->
                Column(Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally) {
                    val product = data[page]
                    Text(product, fontSize = 43.sp)
                    Box(Modifier
                        .fillMaxWidth(0.9f)
                        .fillMaxHeight(0.7f)
                        .padding(top=40.dp)
                        .background(
                            Color(Random.nextInt(255),Random.nextInt(255),Random.nextInt(255),255)
                        )
                    )
                    Box(Modifier.fillMaxWidth(0.9f).padding(top=20.dp)){
                        Text("Описание товара $product", fontSize = 28.sp)
                    }
                    Row {
                        Icon(
                            imageVector = Icons.Default.KeyboardArrowLeft,
                            contentDescription = "Next Page",
                            modifier = Modifier.size(75.dp).clickable {
                                coroutineScope.launch {
                                    pagerState.animateScrollToPage(pagerState.currentPage - 1)
                                }
                            }
                        )
                        Icon(
                            imageVector = Icons.Default.KeyboardArrowRight,
                            contentDescription = "Next Page",
                            modifier = Modifier.size(75.dp).clickable {
                                coroutineScope.launch {
                                    pagerState.animateScrollToPage(pagerState.currentPage + 1)
                                }
                            }
                        )
                    }
                }
            }
        }
    }
}

Для определения кнопок навигации здесь определена строка Row, которая содержит пару иконок Icon:

Кнопки навигации в мобильном приложении на Jetpack Compose на Kotlin в Android

Для каждой иконки определен обработчик нажатия. Для выполнения перехода между страницами применяется метод pagerState.animateScrollToPage(), который переходит к странице с определенным индексом. Но поскольку этот метод представляет suspend-функцию, то он запускается из области корутины

Icon(
    ..........................
    modifier = Modifier.size(75.dp).clickable {
        coroutineScope.launch {
            pagerState.animateScrollToPage(pagerState.currentPage - 1)
        }
    }
)

Для перехода по страницам странице с помощью состояния пагинатора получаем текущую страницу - pagerState.currentPage. Соответственно для получения индекса следующей страницы нам надо прибаить 1, а для получения индекса предыдущей страницы - отнять 1 от номера текущей страницы.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850