Skip to content
This repository has been archived by the owner on Nov 10, 2022. It is now read-only.

The same index for two last items #20

Closed
brystel opened this issue Feb 23, 2022 · 7 comments
Closed

The same index for two last items #20

brystel opened this issue Feb 23, 2022 · 7 comments

Comments

@brystel
Copy link

brystel commented Feb 23, 2022

Describe the bug

Hi,
Thanks for library. It is great!

I've got issues when trying to get current item.
LayoutInfo's return the same currentItem.index for two latest items.
For example, when I got 4 items, after scroll one by one (horizontally) layoutInfo.currentItem?.index should returns 0, 1, 2, 3 index values, however it returns 0, 1, 2, 2 values.

Here is simplified implementation to reproduce issue:

@OptIn(ExperimentalSnapperApi::class)
@Composable
fun TestCode(titles: List<String>) {
    val contentPadding = PaddingValues(start = 16.dp,
                                       end = 16.dp)
    val lazyListState = rememberLazyListState()
    val layoutInfo = rememberLazyListSnapperLayoutInfo(lazyListState,
                                                       snapOffsetForItem = SnapOffsets.Center,
                                                       endContentPadding = contentPadding.calculateEndPadding(LayoutDirection.Ltr))

    LaunchedEffect(lazyListState.isScrollInProgress) {
        if (!lazyListState.isScrollInProgress) {
            val index = layoutInfo.currentItem?.index
            // index will never be equals to last item index.
            // two last items will returns the same index
        }
    }

    LazyRow(
        state = lazyListState,
        contentPadding = contentPadding,
        flingBehavior = rememberSnapperFlingBehavior(layoutInfo),
        horizontalArrangement = Arrangement.spacedBy(24.dp),
        modifier = Modifier.fillMaxWidth()
    ) {
        items(titles) { title ->
            TextField(text = title)
        }
    }
}

Environment:

  • Android OS 11, 12
  • OnePlus7T PRO, Android Emulator
  • Library version: both 0.1.0 and 0.2.0
@chrisbanes
Copy link
Owner

This is a tricky one. Snapper has no control over the layout of the content, but the items here result in the last item not 'covering' the snap offset given. I'll have a think how we can tweak the currentItem to compensate.

@chrisbanes
Copy link
Owner

As a quick workaround, instead of layoutInfo.currentItem, you can use the following to find the item which is closest to the snap offset:

val index = layoutInfo.visibleItems.minByOrNull {
    (it.offset - SnapOffsets.Center(layoutInfo, it)).absoluteValue
}

We probably don't want to ship this in Snapper as it breaks some behaviors.

@brystel
Copy link
Author

brystel commented Mar 15, 2022

Hi,
Thank you for your response.

I've tried proposed workaround and it's working in portrait mode, however in landscape, index is always greater than 0 and less than last item index.
So when I've got items with index 0, 1, 2, 3, only 1 and 2 is returned.

What I am trying to achieve is horizontal scrolling list with cards. Focused card (selected by scroll and snapping behavior) changed it's color and second part of the screen is filled with focused card description.

Do you maybe have another ideas how to get proper index? Maybe I should adjust horizontal content paddings to make it much larger than current 16.dp in landscape?

@chrisbanes
Copy link
Owner

chrisbanes commented Mar 18, 2022

As I said earlier, I can't see a perfect solution here. In the example below (which is scrolled all the way to the end), what item is the 'current' item? It could be 18 or 19, but there's no way to determine that just from looking at the layout.

Screenshot_1647601756

We could look at the velocity (aka target index), but then it's looks pretty much random to the user which item would be selected. Maybe that is better than the current situation though.

Increasing the content padding would work, but that also changes how the items are laid out at the start/end. You've basically re-implemented Accompanist Pager too.

@brystel
Copy link
Author

brystel commented Apr 11, 2022

Thank you for time that you spent with investigating my issue and for answers.
I will think again on my idea of horizontal - focusable list :)

@brystel brystel closed this as completed Apr 11, 2022
@AhmedAshour
Copy link

Hello @chrisbanes,

Thanks for providing such a library it saves so much time.

The same issue occurred to me while using LazyRow in Portrait mode (last two elements show the same index) and I solved it by increasing the contentPadding of the LazyRow, so it would be great if you can add this to the documentation along with how to obtain the current index in the first place as it is not in the documentation too. 🙏🏻

@chrisbanes
Copy link
Owner

Hi, getting the current item is documented here: https://chrisbanes.github.io/snapper/usage/#finding-the-current-item

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants