【发布时间】:2014-02-16 20:33:23
【问题描述】:
有没有办法检测 ListView 是否快速滚动?也就是说,我们能否知道用户何时按下和释放 FastScroller?
【问题讨论】:
标签: android listview fastscroll
有没有办法检测 ListView 是否快速滚动?也就是说,我们能否知道用户何时按下和释放 FastScroller?
【问题讨论】:
标签: android listview fastscroll
反射允许你这样做。通过查看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();
}
}
}
【讨论】:
grid 是我使用的 GridView。我将其更改为list,以便更清楚。
尝试使用 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");
}
});
}
【讨论】: