How to detect if a ListView is fast scrolling

孤者浪人 提交于 2019-12-03 16:41:11

Reflection allows you to do it. By taking a look at the AbsListView source code, there is a FastScroller object which indicates a wrapper around the fast scrolling functionality. Its source code shows an interesting field:

/**
 * Current decoration state, one of:
 * <ul>
 * <li>{@link #STATE_NONE}, nothing visible
 * <li>{@link #STATE_VISIBLE}, showing track and thumb
 * <li>{@link #STATE_DRAGGING}, visible and showing preview
 * </ul>
 */
private int mState;

This field contains the status of the FastScroller object. The solution consists in reading this field's value via reflection, every time the onScroll() and onScrollStateChanged() methods are triggered.

This code implements the solution described above:

private class CustomScrollListener implements OnScrollListener {

    private ListView list;
    private int mState = -1;
    private Field stateField = null;
    private Object mFastScroller;
    private int STATE_DRAGGING;

    public CustomScrollListener() {
        super();

        String fastScrollFieldName = "mFastScroller";
        // this has changed on Lollipop
        if (Build.VERSION.SDK_INT >= 21) {
            fastScrollFieldName = "mFastScroll";
        }

        try {
            Field fastScrollerField = AbsListView.class.getDeclaredField(fastScrollFieldName);
            fastScrollerField.setAccessible(true);
            mFastScroller = fastScrollerField.get(list);

            Field stateDraggingField = mFastScroller.getClass().getDeclaredField("STATE_DRAGGING");
            stateDraggingField.setAccessible(true);
            STATE_DRAGGING = stateDraggingField.getInt(mFastScroller);

            stateField = mFastScroller.getClass().getDeclaredField("mState");
            stateField.setAccessible(true);
            mState = stateField.getInt(mFastScroller);

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {

        // update fast scroll state
        try {
            if (stateField != null) {
                mState = stateField.getInt(mFastScroller);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }


        if (mState == STATE_DRAGGING)) {
            // the user is fast scrolling through the list
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

        // update fast scroll state
        try {
            if (stateField != null) {
                mState = stateField.getInt(mFastScroller);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
}

Try using the setOnScrollListener and implement the onScrollStateChanged. The scrollState can be idle, touch scroll, or fling

setOnScrollListener(new OnScrollListener(){
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
      // TODO Auto-generated method stub
    }
    public void onScrollStateChanged(AbsListView view, int scrollState) {
      // TODO Auto-generated method stub
      if(scrollState == 2) Log.i("a", "fast scroll");
    }
  });
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!