Кнопка прокрутки

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

В ряде приложений применяется кнопка перемещение в начало контента, то есть фактически кнопка прокрутки в начало. Посмотрим, как сделать такую кнопку на Jetpack Compose. Для этого рассмотрим следующее приложение:

package com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.ui.unit.sp
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
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 kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val listState = rememberLazyListState()
            val coroutineScope = rememberCoroutineScope()
            val displayButton =remember { derivedStateOf { listState.firstVisibleItemIndex > 5 } }
            Box(Modifier.fillMaxSize()) {
                LazyColumn(state = listState) {
                    items(30) {
                        Text("Item $it", Modifier.padding(8.dp), fontSize = 28.sp)
                    }
                }
                AnimatedVisibility(visible = displayButton.value, Modifier.align(Alignment.BottomCenter)
                ) {
                    OutlinedButton(
                        onClick = { coroutineScope.launch { listState.scrollToItem(0) } },
                        border = BorderStroke(1.dp, Color.Gray),
                        shape = RoundedCornerShape(50),
                        colors = ButtonDefaults.outlinedButtonColors(contentColor = Color.DarkGray),
                        modifier = Modifier.padding(5.dp)
                    ) { Text("Top", fontSize = 22.sp) }
                }
            }
        }
    }
}

Для управления прокруткой списка применяется состояние LazyListState:

val listState = rememberLazyListState()

Поскольку функции программной прокрутки представляют suspend-функции, и соответственно их надо запускать из корутин, то для программной прокрутки определятся область корутины:

val coroutineScope = rememberCoroutineScope()

И также определяется производное состояние, которое указывает, будет ли отображаться кнопка прокрутки:

val displayButton =remember { derivedStateOf { listState.firstVisibleItemIndex > 5 } }

В данном случае мы говорим, что этот состояние будет равно true, если индекс первого видимого элемента в списке больше 5. А это значит, что кнопка прокрутки будет отображаться. Если же мы находимся в самом начале списка (индекс первого видимого элемента в списке равен или меньше 5), то нет смысла отображать кнопку прокрутки, поэтому это состояние будет равно false.

Для хранения всего интерфейса определяется компонент Box. Здесь список, для которого определяется прокрутка, определен в компоненте LazyList. В данном случае это просто 30 компонентов Text:

LazyColumn(state = listState) {
    items(30) {
        Text("Item $it", Modifier.padding(8.dp), fontSize = 28.sp)
    }
}

Также в Box располагается элемент AnimatedVisibility, который представляет анимацию видимости и будет управлять видимостью кнопки:

AnimatedVisibility(visible = displayButton.value, Modifier.align(Alignment.BottomCenter)) {
    OutlinedButton(
        onClick = { coroutineScope.launch { listState.scrollToItem(0) } },
        border = BorderStroke(1.dp, Color.Gray),
        shape = RoundedCornerShape(50),
        colors = ButtonDefaults.outlinedButtonColors(contentColor = Color.DarkGray),
        modifier = Modifier.padding(5.dp)
    ) { Text("Top", fontSize = 22.sp) }
 }

Этот компонент будет накладываться на список LazyList, но благодаря состоянию displayButton, которое зависит от индекса первого видимого элемента списка, мы сможем автоматически и динамически управлять видимостью этого компонента.

Непосредственно сама кнопка представлена компонентом OutlinedButton - кнопкой, по нажатию на которую происходит запуск корутины, в которой выполняется переход в начало списка с помощью вызова listState.scrollToItem(0)

Таким образом, если мы уйдем вниз по списку, то мы увидим кнопку возврата в начало списка:

Кнопка прокрутки в начало в Jetpack Compose на Kotlin в Android
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850