0

I am using page 3, when displaying data, I found that if the page switches and returns to the bottom page, the data will automatically roll to the top.

If there are two items, it will automatically scroll to the top, if there is one item, there is no problem

val pagingItems = viewModel.windList.collectAsLazyPagingItems()

LazyColumn(Modifier.fillMaxSize()) {
    item {
        ...
    }
    items(pagingItems) { wind ->
        if (wind != null) {
            WindRow(navController, wind)
        }
    }
}

This way is fine

LazyColumn(Modifier.fillMaxSize()) {
    items(pagingItems) { wind ->
        if (wind != null) {
            WindRow(navController, wind)
        }
    }
}

I inevitably use multiple items. How can I solve it?

Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
gaohomway
  • 2,132
  • 1
  • 20
  • 37
  • Just for clarification - are you trying to add a header to the list of paginated items? – dlam Oct 08 '21 at 02:48
  • @dlam No, no header is added, it has something to do with adding a header? – gaohomway Oct 08 '21 at 03:14
  • Please add [kotlin] tag to your questions to add code highlighting to be easier to read – Phil Dukhov Oct 08 '21 at 06:07
  • I'm trying to understand your question - in the first code sample you shared, it looks like you are trying to add some static content above the paginated data. Is adding a header this way what is not working for you, or do you mean when you load more than one item via paging? Can you clarify exactly when it scrolls to the top or share a repro? – dlam Oct 08 '21 at 09:32
  • @dlam Yes, add static content through item, but it doesn't work. As long as static content is added, the page will scroll to the top after the page is switched. – gaohomway Oct 08 '21 at 10:22
  • @dlam It is a very simple paging function, without complicated content, I will produce a project to reproduce this problem later – gaohomway Oct 08 '21 at 10:24

2 Answers2

0

For some reason you have optional wind elements, and your current code will create some number of zero-height cells, which can lead to this behavior. I suggest that you make it non optional, if possible.

Likewise, depending on your design, you may want to display a placeholder, otherwise don't add empty elements like here:

items(pagingItems.filterNotNull()) { wind ->
    WindRow(navController, wind)
}

Or, if your null objects may become non null and you need to display updates, you can do following:

pagingItems.forEachIndexed { i, wind ->
    if (wind != null) {
        item(key = i) {
            WindRow(navController, wind)
        }
    }
}

If none of this helped, please update your code to minimal reproducible example.

Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
  • Hi Philip! I tried your answer but couldn't solve it. I guess this is not a Compose problem. This is a paging 3 problem. According to the official documentation, the item needs to be wrapped in the state. https://developer.android.google.cn/reference/kotlin/androidx/paging/compose/package-summary#extension-functions Guess the number and height of pagination needs to be calculated, and the extra items will be rolled to the top if they are not calculated. – gaohomway Oct 08 '21 at 07:49
  • @weifans in documentation example it doesn't seems to be optional – Phil Dukhov Oct 08 '21 at 07:51
  • My current ending plan is to wrap the extra `item` that need to be added in `itemsIndexed(pagingItems) {index, wind -> }`, and add the content that needs to be added according to the index. This method will not roll back to the top – gaohomway Oct 08 '21 at 08:05
  • @dlam Maybe you will have a better solution, welcome to update the answer – gaohomway Oct 08 '21 at 08:07
  • @weifans you can use `itemsIndexed` with my first sample and my second example already contains index for you to use. If this doesn't help, as I said, you need to provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) – Phil Dukhov Oct 08 '21 at 08:18
  • Hey @PhilipDukhov can help me on this [issue](https://stackoverflow.com/q/69755212/11560810) – Kotlin Learner Oct 29 '21 at 06:47
0

If I'm understanding correctly, every new page load causes you to scroll to top with a static item at the top of your LazyColumn.

My best guess at what is happening here without actually trying it out in a sample, is that on every new page load, paging-compose resubmits the list to LazyColumn. Since there is a static item that is always there though, Compose will keep that item in view, and because that static item is at the top it has the effect of scrolling to top.

For a workaround, you could just use Paging's built-in support for headers

ViewModel.kt

val windList = Pager(..) { ..}
  .map { pagingData ->
    pagingData.insertHeaderItem(..)
  }
  .cachedIn(viewModelScope)
  .collectAsLazyPagingItems()

Also, I would recommend to implement the key mapping in items, as it will help you provide stable ids to Compose's LazyColumn, allowing it to understand how to resume scroll position on refresh or config change.

dlam
  • 3,547
  • 17
  • 20
  • I know that inserting a `insertHeaderItem ` is effective, but it is too inflexible. Whether static content is at the top or bottom, there will be a problem of scrolling to the top. In `LazyColumn`, as long as the extra `item` is included, problems will occur, even if the `item` is empty, problems will occur. – gaohomway Oct 09 '21 at 06:24
  • I guess you are in charge of the work of Paging3. I think the above solution is not feasible and is not the correct solution. You need to reconsider this problem. – gaohomway Oct 09 '21 at 06:29
  • To be clear, this is a workaround - there's a big reason why paging-compose is still in alpha and this question is one of them. Sending incremental updates down to the UI is really "anti-compose" but is required to achieve what you want, so there's a big open design question of what the best way to do this is. – dlam Oct 09 '21 at 07:20
  • Your other idea of using itemsIndexed is also another way we currently recommend of doing this - mapping per item is another way this works (and how you would do sticky headers), but does not support prepending. – dlam Oct 09 '21 at 07:22
  • Understand, we look forward to the stable version, and we also look forward to a better solution to this problem – gaohomway Oct 09 '21 at 07:30