BeksOmega / looping-layout

A looping LayoutManager for the Android RecyclerView.
Apache License 2.0
271 stars 16 forks source link

Implementation of autoscroll in the looping pager #45

Closed ummesulaith closed 3 years ago

ummesulaith commented 3 years ago

:key: Use case

Hi, I was wondering if auto-scroll can be implemented. It will be useful in e-commerce or any other app that has requirement of looping layout.

:hammer: Proposal

:wrench: Alternative

:memo: Other info

:bee: Request for assignment

I'm just requesting this feature.

BeksOmega commented 3 years ago

Hello @ummesulaith! Could you clarify what you mean by autoscroll? The layout manager does support a scrollToPosition function, which may solve your use case =)

ghost commented 3 years ago

I believe @ummesulaith refers to the "carousel like" effect of having the recyclerview moving to the next item, while also being able to scroll manually (and restarting the scroll counter). This is typically where the horizontal list is showing an item that fits the whole width, like a gallery, a hero banner or similar.

I'm actually in the middle of that too, and though it works flawlessly for the most part (during the first transitions, the smoothScrollToPosition is erratic, like the items different from the shown are still not in their "looping" position), it's difficult to know which is the currently visible item position (such as LinearLayoutManager.findFirstVisibleItemPosition()), to know which should be the next position to scroll to. I accomplished almost the whole use case with this workaround:

recyclerView.addOnScrollListener(object: RecyclerView.OnScrollListener() {
    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        skipAutoScroll = true
        super.onScrolled(recyclerView, dx, dy)
    }
})

if (layoutManager is LoopingLayoutManager) {
    CoroutineScope(Dispatchers.Main).async {
        flow {
            while(true) {
                delay(2_000)
                if (skipAutoScroll) {
                    skipAutoScroll = false
                } else {
                    position = (position + 1) % dataset.size
                    emit(position)
                }
            }
        }.collect {
            recyclerView.smoothScrollToPosition(it)
        }
    }

    (layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
}

Where position is 0 by default. skipAutoScroll will be true while you scroll around, and false until the next iteration.

And anyway, I wouldn't say this is a bug, but an enhancement!

BeksOmega commented 3 years ago

@sergijuanola That code snippet looks really cool! Thank you for sharing it :D It really helped me understand what ummesulaith was refering to about as well.

I think you're right that the LoopingLayoutManager needs to provide information about what the adapter indices of important views are (eg the first and last views). As such I've opened #45 which addresses that more directly. Basically it proposes that the LoopingLayoutManager implement findXIndexPosition methods as the LinearLayoutManager =)

If you have any more thoughts about it feel free to share over there or in a new issue, but I think I'm going to close this one down for now.

Thank you again for your reply and sharing that cool code snippet! --Beka