- Реализуйте разбивку по страницам с помощью LazyColumn.
- Когда последний элемент видимы, добавьте дополнительные элементы в список и продолжайте попытки непрерывной прокрутки.
- Элементы добавляются в список, но прокрутка, похоже, зависает. Как только вы перестанете пытаться прокручивать непрерывно, а затем повторите попытку прокрутки через 1 секунду, список будет прокручен.
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import apps.muxy.compose.MainViewModel
import apps.muxy.compose.ui.theme.ComposeTheme
@Composable
fun PaginatedList(
viewModel: MainViewModel,
modifier: Modifier = Modifier
) {
val lazyListState = rememberLazyListState()
val names = viewModel.names
val loaderVisible = viewModel.loaderVisible
LaunchedEffect(Unit) { viewModel.loadMore() }
LazyColumn(state = lazyListState, modifier = modifier) {
items(count = names.size, key = { names[it] }) {
Name(names[it])
}
if (loaderVisible) {
item { ListLoader() }
}
}
OnBottomReached(lazyListState = lazyListState) { viewModel.loadMore() }
}
@Composable
private fun Name(name: String, modifier: Modifier = Modifier) {
Text(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 4.dp)
.border(width = 1.dp, color = Color.LightGray, shape = RoundedCornerShape(4.dp))
.padding(12.dp),
text = name,
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.SemiBold
)
}
@Composable
private fun ListLoader() {
Box(
Modifier
.fillMaxWidth()
.height(40.dp)
.background(Color.Red)
)
}
@Composable
private fun OnBottomReached(lazyListState: LazyListState, buffer: Int = 0, loadMore: () -> Unit) {
val shouldLoadMore = remember {
derivedStateOf {
val lastVisibleItem =
lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()
?: return@derivedStateOf false
lastVisibleItem.index >= lazyListState.layoutInfo.totalItemsCount - buffer - 1
}
}
LaunchedEffect(shouldLoadMore.value) {
if (shouldLoadMore.value) {
loadMore()
}
}
}
Модель просмотра
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.time.Duration.Companion.seconds
class MainViewModel : ViewModel() {
var names by mutableStateOf(mutableListOf())
var loaderVisible by mutableStateOf(false)
private var currentIndex = 0
fun loadMore() {
viewModelScope.launch {
loaderVisible = true
delay(5.seconds)
val mutableNames = names.toMutableList()
for (i in currentIndex..(currentIndex + PAGE_COUNT)) {
mutableNames.add("Name $i")
}
currentIndex += PAGE_COUNT
currentIndex++
loaderVisible = false
names = mutableNames
}
}
companion object {
private const val PAGE_COUNT = 20
}
}
Подробнее здесь: https://stackoverflow.com/questions/791 ... ng-and-scr