实现onScrollListener以检测ListView中滚动的结束

我正在ListView展示一些物品。我想对的可见部分中当前显示的项目执行一些操作ListView,具体取决于的ListView滚动方式;因此,我想到了实现OnScrollListener的ListView。根据Android api参考,onScroll方法“将在滚动完成后调用”。在我看来,这似乎是我所需要的,因为滚动完成后,我在on上执行我的操作ListView(onScroll方法返回显示的第一个项目的索引和显示的项目数)。


但是一旦实现,我从中看到LogCatonScroll方法不仅在滚动完成后被触发,而且从滚动的开始到结束,都会为进入显示视图的每个新项目触发。这不是我所期望的行为,也不是我所需要的。侦听器的另一种方法(onScrollStateChanged)不提供有关当前显示在中的项目的信息ListView。


那么,有谁知道如何使用这两种方法来检测滚动的结束并获取有关所显示项目的信息?api引用与方法的实际行为之间的不一致使我有些困惑。提前致谢。


PS:我看过一些类似的话题,但是没有什么可以帮助我理解整个过程。


MM们
浏览 536回答 3
3回答

缥缈止盈

最终,我找到了一个不太优雅的解决方案,但是对我有用。弄清楚onScroll方法是在滚动的每个步骤中调用的,而不仅仅是在滚动端被调用,并且onScrollStateChanged实际上仅在滚动完成时才被调用,我这样做是:public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {    this.currentFirstVisibleItem = firstVisibleItem;    this.currentVisibleItemCount = visibleItemCount;}public void onScrollStateChanged(AbsListView view, int scrollState) {    this.currentScrollState = scrollState;    this.isScrollCompleted(); }private void isScrollCompleted() {    if (this.currentVisibleItemCount > 0 && this.currentScrollState == SCROLL_STATE_IDLE) {        /*** In this way I detect if there's been a scroll which has completed ***/        /*** do the work! ***/    }}实际上,每次滚动ListView时,我都会保存有关第一个可见项和可见项计数的数据(onScroll方法);当滚动状态更改(onScrollStateChanged)时,我保存了状态,并调用了另一个方法,该方法实际上了解滚动是否完成以及滚动是否完成。这样,我也可以获得有关所需可见项目的数据。也许不干净,但是行得通!

狐的传说

@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,&nbsp; int visibleItemCount, int totalItemCount) {&nbsp; if (list.getLastVisiblePosition() == list.getAdapter().getCount() - 1&nbsp; &nbsp; &nbsp; && list.getChildAt(list.getChildCount() - 1).getBottom() <= list.getHeight()) {&nbsp; &nbsp; // Scroll end reached&nbsp; &nbsp; // Write your code here&nbsp; }}

杨__羊羊

降低这种行为是棘手的,并且花了我相当长的时间才能使它变得完美。问题的根源在于,据我所知,滚动侦听器本身实际上还不足以检测“滚动停止”(包括方向按钮/轨迹球)。我最终做了一些符合我期望的工作。我认为我能做到的最好方法是扩展ListView并重写一些方法:&nbsp; ....&nbsp; @Override&nbsp; public boolean onKeyUp(int keyCode, KeyEvent event) {&nbsp; &nbsp; if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_UP) {&nbsp; &nbsp; &nbsp; startWait();&nbsp; &nbsp; }&nbsp; &nbsp; return super.onKeyUp(keyCode, event);&nbsp; }&nbsp; @Override&nbsp; public boolean onTouchEvent(MotionEvent event) {&nbsp; &nbsp; if (event.getAction() == MotionEvent.ACTION_DOWN) {&nbsp; &nbsp; &nbsp; stopWait();&nbsp; &nbsp; }&nbsp; &nbsp; if (event.getAction() == MotionEvent.ACTION_UP ||&nbsp; &nbsp; &nbsp; &nbsp; event.getAction() == MotionEvent.ACTION_CANCEL) {&nbsp; &nbsp; &nbsp; startWait();&nbsp; &nbsp; }&nbsp; &nbsp; return super.onTouchEvent(event);&nbsp; }&nbsp; private OnScrollListener customScrollListener = new OnScrollListener() {&nbsp; &nbsp; @Override&nbsp; &nbsp; public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,&nbsp; &nbsp; &nbsp; int totalItemCount) {&nbsp; &nbsp; &nbsp; stopWait();&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public void onScrollStateChanged(AbsListView view, int scrollState) {&nbsp; &nbsp; &nbsp; if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {&nbsp; &nbsp; &nbsp; &nbsp; startWait();&nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; stopWait();&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; };&nbsp; //All this waiting could be improved, but that's the idea&nbsp; private Thread waitThread = null;&nbsp; private int waitCount&nbsp; = Integer.MIN_VALUE;&nbsp; public void stopWait() {&nbsp; &nbsp; waitCount = Integer.MIN_VALUE;&nbsp; }&nbsp; public synchronized void startWait() {&nbsp; &nbsp; waitCount = 0;&nbsp; &nbsp; if (waitThread != null) {&nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; }&nbsp; &nbsp; waitThread = new Thread(new Runnable() {&nbsp; &nbsp; @Override&nbsp; &nbsp; public void run() {&nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; for (; waitCount.get() < 10; waitCount++) {&nbsp; &nbsp; &nbsp; &nbsp; Thread.sleep(50);&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; //Kick it back to the UI thread.&nbsp; &nbsp; &nbsp; &nbsp; view.post(theRunnableWithYourOnScrollStopCode); // HERE IS WHERE YOU DO WHATEVER YOU WANTED TO DO ON STOP&nbsp; &nbsp; &nbsp; } catch (InterruptedException e) {&nbsp; &nbsp; &nbsp; } finally&nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; waitThread = null;&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; });&nbsp; waitThread.start();}请注意,您还必须customScrollListener在构造函数中绑定。我认为该实现很好,因为它不会立即触发“事件”,因此会稍等一会,直到它完全停止滚动为止。
打开App,查看更多内容
随时随地看视频慕课网APP