How to disable overscroll effect on RecyclerView ONLY when you can't scroll anyway ?

微笑、不失礼 提交于 2020-08-21 08:03:21

问题


Background

Sometimes, all items of the recyclerView are already visible to the user.

In this case, it wouldn't matter to the user to see overscroll effect, because it's impossible to actually scroll and see more items.

The problem

I know that in order to disable overscroll effect on RecyclerView, I can just use:

recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);

but I can't find out when to trigger this, when the scrolling isn't possible anyway.

The question

How can I Identify that all items are fully visible and that the user can't really scroll ?

If it helps to assume anything, I always use LinearLayoutManager (vertical and horizontal) for the RecyclerView.


回答1:


you could give OVER_SCROLL_IF_CONTENT_SCROLLS a try. Accordingly to the documentation

Allow a user to over-scroll this view only if the content is large enough to meaningfully scroll, provided it is a view that can scroll.

Or you could check if you have enough items to trigger the scroll and enable/disable the over scroll mode, depending on it. Eg

boolean notAllVisible = layoutManager.findLastCompletelyVisibleItemPosition() < adapter.getItemCount() - 1;
if (notAllVisible) {
   recyclerView.setOverScrollMode(allVisible ? View.OVER_SCROLL_NEVER);
}



回答2:


<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:overScrollMode="never"/>

Just add android:overScrollMode="never" in XML




回答3:


You could try something like this:

totalItemCount = linearLayoutManager.getItemCount();
firstVisibleItem = linearLayoutManager.findFirstCompletelyVisibleItemPosition()
lastVisibleItem = linearLayoutManager.findLastCompletelyVisibleItemPosition();

if(firstVisibleItem == 0 && lastVisibleItem -1 == totalItemCount){
    // trigger the overscroll effect
}

Which you could add in the onScrolled() of an OnScrollListener that you add on your RecyclerView.




回答4:


Since android:overScrollMode="ifContentScrolls" is not working for RecyclerView(see https://issuetracker.google.com/issues/37076456) I found some kind of a workaround which want to share with you:

class MyRecyclerView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr) {

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        super.onLayout(changed, l, t, r, b)
        val canScrollVertical = computeVerticalScrollRange() > height
        overScrollMode = if (canScrollVertical) OVER_SCROLL_ALWAYS else OVER_SCROLL_NEVER
    }
}



回答5:


Longer workaround, based on here (to solve this issue), handles more cases, but still a workaround:

/**a temporary workaround to make RecyclerView handle android:overScrollMode="ifContentScrolls"  */
class NoOverScrollWhenNotNeededRecyclerView : RecyclerView {
    private var enableOverflowModeOverriding: Boolean? = null
    private var isOverFlowModeChangingAccordingToSize = false

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    override fun setOverScrollMode(overScrollMode: Int) {
        if (!isOverFlowModeChangingAccordingToSize)
            enableOverflowModeOverriding = overScrollMode == View.OVER_SCROLL_IF_CONTENT_SCROLLS
        else isOverFlowModeChangingAccordingToSize = false
        super.setOverScrollMode(overScrollMode)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        super.onLayout(changed, l, t, r, b)
        if (enableOverflowModeOverriding == null)
            enableOverflowModeOverriding = overScrollMode == View.OVER_SCROLL_IF_CONTENT_SCROLLS
        if (enableOverflowModeOverriding == true) {
            val canScrollVertical = computeVerticalScrollRange() > height
            val canScrollHorizontally = computeHorizontalScrollRange() > width
            isOverFlowModeChangingAccordingToSize = true
            overScrollMode = if (canScrollVertical || canScrollHorizontally) OVER_SCROLL_ALWAYS else OVER_SCROLL_NEVER
        }
    }
}


来源:https://stackoverflow.com/questions/41381621/how-to-disable-overscroll-effect-on-recyclerview-only-when-you-cant-scroll-anyw

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!