简体   繁体   English

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

[英]Screen scrolls to the top (Jetpack Compose Pagination)

I am trying to do pagination in my application.我正在尝试在我的应用程序中进行分页。 First, I'm fetching 20 item from Api (limit) and every time i scroll down to the bottom of the screen, it increase this number by 20 ( nextPage() ).首先,我从 Api (限制)中获取 20 个项目,每次我向下滚动到屏幕底部时,它都会将该数字增加 20( nextPage() )。 However, when this function is called, the screen goes to the top, but I want it to continue where it left off.但是,当调用此 function 时,屏幕会转到顶部,但我希望它从中断的地方继续。 How can I do that?我怎样才能做到这一点?

Here is my code:这是我的代码:

CharacterListScreen:字符列表屏幕:

@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: 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)
            }
    }

}

CharacterListState:字符列表状态:

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

Call scrollToItem from a LaunchedEffect.从 LaunchedEffect 调用scrollToItem Something like this:像这样的东西:

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

    val state = characterListViewModel.state.value
    val limit = characterListViewModel.limit.value
    
    LaunchedEffect(state.characters.itemCount) {
       state.scrollToItem(state.characters.itemCount - 1, 0)
    }

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

            }
        }
    }
}

I think the issue here is that you are creating CharacterListState(isLoading = true) while loading.我认为这里的问题是您在加载时创建CharacterListState(isLoading = true) This creates an object with empty list of elements.这将创建一个带有空元素列表的 object。 So compose renders an empty LazyColumn here which resets the scroll state.所以 compose 在这里渲染一个空的LazyColumn来重置滚动 state。 The easy solution for that could be state.value = state.value.copy(isLoading = true) .简单的解决方案可能是state.value = state.value.copy(isLoading = true) Then, while loading, the item list can be preserved (and so is the scroll state)然后,在加载时,可以保留项目列表(滚动状态也是如此)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM