实现onScrollListener来检测ListView中的滚动结束
我有一个ListView
显示一些项目。 我想对当前显示在ListView
的可见部分中的项目执行一些操作,具体取决于ListView
如何滚动; 因此我想实现ListView
的OnScrollListener
。 根据Android API参考,onScroll方法“将在滚动完成后调用”。 这在我看来是正确的,因为一旦滚动完成,我在ListView
上执行我的操作(onScroll方法返回显示的第一个项目的索引和显示的项目数)。
但是一旦实现,我从LogCat
中看到onScroll方法不仅在滚动完成后触发,而且从滚动的开始到结束,每进入一个显示视图的新项目都会触发onScroll方法。 这不是我所期望的行为,也不是我所需要的。 监听器的另一种方法(onScrollStateChanged)不提供有关当前在ListView
显示的项目的信息。
那么,有没有人知道如何使用这几个方法来检测滚动的结尾,并获得有关显示项目的信息? API参考和方法的实际行为之间的不一致让我困惑了一下。 提前致谢。
PS:我已经看到了一些类似的话题,但没有任何帮助我理解整个事情是如何工作的。
最后,我已经达成了一个不那么高雅的解决scheme,但是这对我来说很有效。 已经知道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)我保存状态,我调用另一种方法,实际上了解是否有一个滚动,如果它完成。 通过这种方式,我也有关于我需要的可见项目的数据。 也许不干净,但工作!
问候
@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 } }
@Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if((firstVisibleItem + visibleItemCount) == totalItemCount) { Log.i("Info", "Scroll Bottom" ); } }});
为了减less这种行为是棘手的,并花了我一段时间来完善。 问题的关键是,据我所知,滚动听众本身并不足以检测到“滚动停止”(包括方向button/轨迹球)。 我最终做了一些正确的事情,就像我期待的那样。
我想我能做到的最好的方法是扩展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(); }
请注意,您还必须在构造函数中绑定customScrollListener
。 我认为这个实现是很好的,因为它不会立即触发“事件”,它将等待一段时间,直到它实际完全停止滚动。
试试这个…
@Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { int position = firstVisibleItem+visibleItemCount; int limit = totalItemCount; // Check if bottom has been reached if (position >= limit && totalItemCount > 0) { //scroll end reached //Write your code here } }
电子卡尔的答案只是更有用的代表
监听器实现:
public abstract class OnScrollFinishListener implements AbsListView.OnScrollListener { int mCurrentScrollState; int mCurrentVisibleItemCount; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { mCurrentScrollState = scrollState; if (isScrollCompleted()) { onScrollFinished(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mCurrentVisibleItemCount = visibleItemCount; } private boolean isScrollCompleted() { return mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE; } protected abstract void onScrollFinished(); }
用法:
listView.setOnScrollListener(new OnScrollFinishListener() { @Override protected void onScrollFinished() { // do whatever you need here! } });
分析以前的答案,find了自己的:
在onViewCreated,onCreate或任何你抓住你的列表视图:
ListView list = (ListView) view.findViewById(R.id.[your id]); list.setOnScrollListener(this);
然后填写监听器方法:
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // yes, just leave it empty } public void onScrollStateChanged(AbsListView view, int scrollState) { this.isScrollCompleted(view, scrollState); } private void isScrollCompleted(AbsListView view, int scrollState) { if (!view.canScrollVertically(1) && this.currentScrollState == SCROLL_STATE_IDLE) { // do work } }
似乎它应该做的:检测列表的末尾没有吨代码和适配器的修改。
还有一个更简单的解决scheme。 把一个监听器的ListView的适配器,并在getview中检查是否(位置== totalItemCount的项目在数组中显示),如果是我从适配器和监听器调用我的监听器无论它是什么运行
当我试图找出列表是否位于OnScrollListener的底部时,遇到了很多问题,我发现最好的解决scheme是从适配器的getView方法中检查,如果我正在显示最后一行:
@Override public View getView(int position, View convertView, ViewGroup parent) { ActivityView view; if (convertView==null) view = (ActivityView)inflater.inflate(R.layout.activity_item, null); else view = (ActivityView)convertView; view.showRow(activitiesList.get(position),position,controller,this); if(position == activitiesList.size() - 1) { Log.i("BOTTOM","reached"); } return view; }
在那里我可以很容易地创build一个接口来通知我到达底部的片段/活动。
干杯。
- 如何从任何地方获取包名?
- 在com.android.build.gradle.internal.api.ApplicationVariantImpl找不到属性'outputFile'
- 渲染问题渲染过程中引发exception:com / android / util / PropertiesMap
- ICS中的TYPE_SYSTEM_OVERLAY
- 在Android的onPreviewFrame期间转换YUV-> RGB(image processing) – > YUV?
- 使用Phonegap / jQuery Mobile Android和iOS应用程序下载文件并将其存储在本地
- 从Java代码中指定DIP尺寸的正确方法是什么?
- onActivityResult RESULT_OK无法parsing为Android中的variables?
- Android – 编写一个自定义(复合)组件