Кроме автоматической прокрутки с помощью пролистывания пальцев на экране устройства Jetpack Compose также поддерживает программную прокрутку, которую можно выполнить из кода Kotlin. Это может быть полезно, когда нам надо изменить текущую позицию в списке, перейти к какому-то определенному элементу в этом списке.
При работе со контейнерами Column и Row программную прокрутку можно выполнить с помощью функций объекта ScrollState:
animateScrollTo(value: Int) - плавная прокрутка до указанной позиции пикселя в списке с использованием анимации
scrollTo(value: Int) - мгновенная прокрутка до указанной позиции пикселя
Печальная сторона этих функций заключается в том, что их параметры представляют позицию в пикселях, а не номер элемента. То есть начало списка представлено позицией пикселя 0, но позиция пикселя, представляющая конец списка, может быть менее очевидной. К счастью, максимальную позицию прокрутки можно определить, обратившись к свойству maxValue:
val maxScrollPosition = scrollState.maxValue
Также стоит учитывать, что это suspend-функции, поэтому их необходимо вызывать из корутин.
Например, определим код для прокрутки в последнему элементу в контейнере Column:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Text import androidx.compose.ui.unit.sp import androidx.compose.runtime.rememberCoroutineScope 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 scrollState = rememberScrollState() val coroutineScope = rememberCoroutineScope() Column(Modifier.verticalScroll(scrollState)) { Text("В конец", Modifier.padding(8.dp).background(Color.DarkGray).padding(5.dp).clickable { coroutineScope.launch() { scrollState.animateScrollTo(scrollState.maxValue) } }, fontSize = 28.sp, color = Color.White) repeat(20){ Text("Item $it", Modifier.padding(8.dp), fontSize = 28.sp) } } } } }
В начале контейнера Column здесь определен компонент Text, по нажатию на который вызывается корутина, которая выполняет функцию scrollState.animateScrollTo()
Для программной прокрутки списков LazyColumn и LazyRow применяются функции объекта LazyListState, который можно получить с помощью вызова функции rememberLazyListState():
val listState = rememberLazyListState()
Затем этои объект передается параметру state:
LazyColumn(state = listState....
Для собственно прокрутки вызываются следующие методы LazyListState:
animateScrollToItem(index: Int) — плавная прокрутка к указанному элементу списка (где 0 — первый элемент)
scrollToItem(index: Int) — мгновенная прокрутка к указанному элементу списка (где 0 — первый элемент)
Это тоже suspend-функции, которые должны запускаться из корутин. Применение:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.Text import androidx.compose.ui.unit.sp import androidx.compose.runtime.rememberCoroutineScope 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() LazyColumn(state=listState) { item{Text("В конец", Modifier.padding(8.dp).background(Color.DarkGray).padding(5.dp).clickable { coroutineScope.launch() { listState.animateScrollToItem(19) } }, fontSize = 28.sp, color = Color.White) } items(20){ Text("Item $it", Modifier.padding(8.dp), fontSize = 28.sp) } } } } }
В данном случае создается аналогичный список с 20 компонентами Text плюс начальный Text, который выполняет роль кнопки перехода к 19-му элементу в списке.