onScrollListener的实现,用于检测ListView中滚动的结束

e-c*_*cal 42 android listview onscroll

ListView展示了一些物品.我想对当前显示在可见部分的项目执行一些操作ListView,具体取决于ListView滚动的方式; 因此我想要实现OnScrollListenerListView.根据Android api引用,onScroll方法"将在滚动完成后调用".这似乎是我所需要的,因为一旦滚动完成,我就会对其执行操作ListView(onScroll方法返回显示的第一个项目的索引和显示的项目数).

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

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

PS:我已经看到了一些类似的话题,但没有什么能帮助我理解整个事情的运作方式......!

e-c*_*cal 54

最后,我找到了一个不那么优雅的解决方案,但这对我有用; 已经发现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! ***/
    }
}
Run Code Online (Sandbox Code Playgroud)

实际上,每次滚动ListView时,我都会保存有关第一个可见项和可见项计数的数据(onScroll方法); 当滚动状态发生变化时(onScrollStateChanged)我保存状态,然后调用另一个实际了解是否有滚动以及是否已完成的方法.通过这种方式,我还可以获得有关我需要的可见项目的数据.也许不干净但有效!

问候


Dun*_*una 13

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

  if (list.getLastVisiblePosition() == list.getAdapter().getCount() - 1
      && list.getChildAt(list.getChildCount() - 1).getBottom() <= list.getHeight()) {
    // Scroll end reached
    // Write your code here
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 9

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

            if((firstVisibleItem + visibleItemCount) ==  totalItemCount)
            {
                Log.i("Info", "Scroll Bottom" );
            }
        }});
Run Code Online (Sandbox Code Playgroud)


dmo*_*mon 6

让这种行为失败是很棘手的,并花了我很长时间来完善.问题的关键在于滚动侦听器本身并不足以检测到"滚动停止"(包括方向按钮/轨迹球),据我所知.我最终做了一些我认为合适的事情.

我认为我能做到的最好的方法是扩展ListView并覆盖一些方法:

  ....
  @Override
  public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN || keyCode == KeyEvent.KEYCODE_DPAD_UP) {
      startWait();
    }
    return super.onKeyUp(keyCode, event);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
      stopWait();
    }
    if (event.getAction() == MotionEvent.ACTION_UP ||
        event.getAction() == MotionEvent.ACTION_CANCEL) {
      startWait();
    }
    return super.onTouchEvent(event);
  }

  private OnScrollListener customScrollListener = new OnScrollListener() {
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
      int totalItemCount) {
      stopWait();
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
      if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
        startWait();
      } else {
        stopWait();
      }
    }
  };

  //All this waiting could be improved, but that's the idea
  private Thread waitThread = null;
  private int waitCount  = Integer.MIN_VALUE;

  public void stopWait() {
    waitCount = Integer.MIN_VALUE;
  }

  public synchronized void startWait() {
    waitCount = 0;

    if (waitThread != null) {
      return;
    }

    waitThread = new Thread(new Runnable() {
    @Override
    public void run() {
    try {
      for (; waitCount.get() < 10; waitCount++) {
        Thread.sleep(50);
      }

        //Kick it back to the UI thread.
        view.post(theRunnableWithYourOnScrollStopCode); // HERE IS WHERE YOU DO WHATEVER YOU WANTED TO DO ON STOP
      } catch (InterruptedException e) {
      } finally  {
        waitThread = null;
      }
    }
  });
  waitThread.start();
}
Run Code Online (Sandbox Code Playgroud)

请注意,您还必须绑定customScrollListener构造函数.我认为这个实现很好,因为它不会立即触发"事件",它会等待一段时间直到它实际上完全停止滚动.