【问题标题】:How to detect if a ListView is fast scrolling如何检测 ListView 是否快速滚动
【发布时间】:2014-02-16 20:33:23
【问题描述】:

有没有办法检测 ListView 是否快速滚动?也就是说,我们能否知道用户何时按下和释放 FastScroller?

【问题讨论】:

    标签: android listview fastscroll


    【解决方案1】:

    反射允许你这样做。通过查看AbsListView source code,有一个FastScroller 对象表示快速滚动功能的包装。 Its source code 展示了一个有趣的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;
    

    此字段包含FastScroller 对象的状态。解决方案是在每次触发onScroll()onScrollStateChanged() 方法时通过反射读取该字段的值。

    这段代码实现了上述解决方案:

    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();
            }
    
        }
    }
    

    【讨论】:

    • fastScrollerField.get(grid) 中的“grid”字段是什么;使用它有什么缺点吗,我认为反射会使这个“慢”
    • grid 是我使用的 GridView。我将其更改为list,以便更清楚。
    • 还假设如果源从 sdk 更改为 sdk 可能会中断?因此尝试捕获。似乎是一个 hacky 解决方案
    • 是的,它很老套,是的,它已经改变了,但只有一次。我正在用两种变体更新答案。 IMO,这是唯一可行的方法。
    • 正确,它可以工作!杰出的! +1但就像你说的那样,它已经改变了,所以字段变量现在是“mFastScroll”。必须是更好的方式嗯
    【解决方案2】:

    尝试使用 setOnScrollListener 并实现 onScrollStateChanged。 scrollState 可以是 idle、touch scroll 或 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");
        }
      });
    }
    

    【讨论】:

    • 这并不意味着它很快。即使用户几乎没有加速度,这也会触发滚动。
    • 您是否要确定它的滚动速度?
    • 我已经尝试过了,滚动触摸屏幕或滚动 fastScroller 返回相同的滚动状态。我正在使用具有 SLIDE_IN 效果的 JazzyListView 并在 ListView 中启用了快速滚动。当我快速滚动时,它不能正常工作,因为第一个或最后一个可见项目很多时候是不可见的。我想在进入快速滚动模式时禁用效果并在离开时重新启用它。
    • 似乎没有办法确定何时使用快速滚动。有一个关于它的bug report 说已经发布了修复程序,但我在文档中找不到任何关于它的内容。
    猜你喜欢
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多