屏幕滚动到顶部(Jetpack Compose 分页)

Screen scrolls to the top (Jetpack Compose Pagination)

我正在尝试在我的应用程序中进行分页。首先,我从 Api(限制)中获取 20 个项目,每次我向下滚动到屏幕底部时,它都会将这个数字增加 20(nextPage())。但是,调用此函数时,屏幕会转到顶部,但我希望它从中断处继续。我该怎么做?

这是我的代码:

字符列表屏幕:

@Composable
fun CharacterListScreen(
    characterListViewModel: CharacterListViewModel = hiltViewModel()
) {

    val state = characterListViewModel.state.value
    val limit = characterListViewModel.limit.value

    Box(modifier = Modifier.fillMaxSize()) {
        val listState = rememberLazyListState()

        LazyColumn(modifier = Modifier.fillMaxSize(), state = listState) {
            itemsIndexed(state.characters) { index, character ->
                characterListViewModel.onChangeRecipeScrollPosition(index)
                if ((index + 1) >= limit) {
                    characterListViewModel.nextPage()
                }
                CharacterListItem(character = character)
            }
        }

        if (state.error.isNotBlank()) {
            Text(
                text = state.error,
                color = MaterialTheme.colors.error,
                textAlign = TextAlign.Center,
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 20.dp)
                    .align(Alignment.Center)
            )
        }
        if (state.isLoading) {
            CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
        }
    }
}

CharacterListViewModel:

@HiltViewModel
class CharacterListViewModel @Inject constructor(
    private val characterRepository: CharacterRepository
) : ViewModel() {

    val state = mutableStateOf(CharacterListState())
    val limit = mutableStateOf(20)
    var recipeListScrollPosition = 0

    init {
        getCharacters(limit.value, Constants.HEADER)
    }

    private fun getCharacters(limit : Int, header : String) {
        characterRepository.getCharacters(limit, header).onEach { result ->
            when(result) {
                is Resource.Success -> {
                    state.value = CharacterListState(characters = result.data ?: emptyList())
                }
                is Resource.Error -> {
                    state.value = CharacterListState(error = result.message ?: "Unexpected Error")
                }
                is Resource.Loading -> {
                    state.value = CharacterListState(isLoading = true)
                }
            }
        }.launchIn(viewModelScope)
    }

    private fun incrementLimit() {
        limit.value = limit.value + 20
    }

    fun onChangeRecipeScrollPosition(position: Int){
        recipeListScrollPosition = position
    }

    fun nextPage() {
            if((recipeListScrollPosition + 1) >= limit.value) {
                incrementLimit()
                characterRepository.getCharacters(limit.value, Constants.HEADER).onEach {result ->
                    when(result) {
                        is Resource.Success -> {
                            state.value = CharacterListState(characters = result.data ?: emptyList())
                        }
                        is Resource.Error -> {
                            state.value = CharacterListState(error = result.message ?: "Unexpected Error")
                        }
                        is Resource.Loading -> {
                            state.value = CharacterListState(isLoading = true)
                        }
                    }
                }.launchIn(viewModelScope)
            }
    }

}

字符列表状态:

data class CharacterListState(
    val isLoading : Boolean = false,
    var characters : List<Character> = emptyList(),
    val error : String = ""
)

不确定您是否正确使用了 LazyListState。在您的视图模型中,创建一个 LazyListState 实例:

val lazyListState: LazyListState = LazyListState()

将其传递到您的可组合项中并按如下方式使用它:

@Composable
fun CharacterListScreen(
    characterListViewModel: CharacterListViewModel = hiltViewModel()
) {

    val limit = characterListViewModel.limit.value

    Box(modifier = Modifier.fillMaxSize()) {
        
        LazyColumn(modifier = Modifier.fillMaxSize(), state = characterListViewModel.lazyListState) {
            itemsIndexed(state.characters) { index, character ->

            }
        }
    }
}

我认为这里的问题是您在加载时正在创建 CharacterListState(isLoading = true)。这将创建一个具有空元素列表的对象。所以 compose 在这里呈现一个空的 LazyColumn 来重置滚动状态。最简单的解决方案可能是 state.value = state.value.copy(isLoading = true)。然后,在加载时,可以保留项目列表(滚动状态也是如此)