From 同站;http://blog.csdn.net/qeqeqe236/article/details/7289112



SCROLL_STATE_FLING是指手指快速拖动后,手指离开,页面惯性滑动的状态。



ListView之滚动事件--OnScrollListener


在onScrollStateChanged(AbsListView view, int scrollState) 中,scrollState有三种状态,分别是开始滚动(SCROLL_STATE_FLING),正在滚动(SCROLL_STATE_TOUCH_SCROLL), 已经停止(SCROLL_STATE_IDLE),对于滚动事件的处理,很有必要知道。


ListView继承自AbsListView
AbsListView中有一个滚动事件的Listenter,如下:
public interface OnScrollListener {

/**
* The view is not scrolling. Note navigating the list using the trackball counts as
* being in the idle state since these transitions are not animated.
*/
public static int SCROLL_STATE_IDLE = 0;

/**
* The user is scrolling using touch, and their finger is still on the screen
*/
public static int SCROLL_STATE_TOUCH_SCROLL = 1;

/**
* The user had previously been scrolling using touch and had performed a fling. The
* animation is now coasting to a stop
*/
public static int SCROLL_STATE_FLING = 2;

/**
* Callback method to be invoked while the list view or grid view is being scrolled. If the
* view is being scrolled, this method will be called before the next frame of the scroll is
* rendered. In particular, it will be called before any calls to
* {@link Adapter#getView(int, View, ViewGroup)}.
*
* @param view The view whose scroll state is being reported
*
* @param scrollState The current scroll state. One of {@link #SCROLL_STATE_IDLE},
* {@link #SCROLL_STATE_TOUCH_SCROLL} or {@link #SCROLL_STATE_IDLE}.
*/
public void onScrollStateChanged(AbsListView view, int scrollState);

/**
* Callback method to be invoked when the list or grid has been scrolled. This will be
* called after the scroll has completed
* @param view The view whose scroll state is being reported
* @param firstVisibleItem the index of the first visible cell (ignore if
* visibleItemCount == 0)
* @param visibleItemCount the number of visible cells
* @param totalItemCount the number of items in the list adaptor
*/
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount);
}

****************************************************************************************************************************************
private boolean mBusy=false; //滚动中
private OnScrollListener mOnScrollListener = new OnScrollListener(){
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case OnScrollListener.SCROLL_STATE_IDLE:
mBusy = false;
break;
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
mBusy = true;
break;
case OnScrollListener.SCROLL_STATE_FLING:
mBusy = true;
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
};
****************************************************
OnScrollListener还可以方便的实现动态加载数据。
遇到问题要多思考。多动脑,少动手~~!




import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.widget.AbsListView;import android.widget.ArrayAdapter;import android.widget.ListAdapter;import android.widget.ListView;import android.widget.AbsListView.OnScrollListener;public class ListViewActivity extends Activity { private ListView lv; private List list; private int lastItem; private int listSize; private ListAdapter adapter; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); lv = (ListView) findViewById(R.id.lv); adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, getData()); lv.setAdapter(adapter); lv.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView paramAbsListView, int paramInt) { //当屏幕停止滚动时为0;当屏幕滚动且用户使用的触碰或手指还在屏幕上时为1; //由于用户的操作,屏幕产生惯性滑动时为2 System.out.println("***lastItem:"+lastItem); System.out.println("***listSize:"+listSize); if(lastItem == listSize){ System.out.println("**************"); //数据全部显示出来时运行此处代码,如果要实现分页功能,在这里加载下一页的数据 } } @Override public void onScroll(AbsListView paramAbsListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {// // firstVisibleItem表示在现时屏幕第一个ListItem(部分显示的ListItem也算)// // 在整个ListView的位置(下标从0开始) // System.out.println("***firstParamInt:"+firstVisibleItem);// // visibleItemCount表示在现时屏幕可以见到的ListItem(部分显示的ListItem也算)总数// System.out.println("***visibleItemCount:"+visibleItemCount);// // totalItemCount表示ListView的ListItem总数// System.out.println("***totalItemCount:"+totalItemCount); // listView.getLastVisiblePosition()表示在现时屏幕最后一个ListItem(最后ListItem要完全 // 显示出来才算)在整个ListView的位置(下标从0开始)// System.out.println("****"+String.valueOf(lv.getLastVisiblePosition())); lastItem = lv.getLastVisiblePosition(); } }); } private List getData(){ int i; list = new ArrayList(); for(i=1; i<10; i++){ list.add("ListView"+i); } listSize = list.size()-1; return list; }} 如果还有什么不懂的,见意去看下源码。




OnScrollListener回调分析



如果adapter中的数据量很大的时候,在加载listview时会出现卡顿的现象。这是会让用户抓狂!最好的解决办法就是先加载一定数量的数据,然后在最下方提示正在加载!
动态加载就是把放入adapter中的数据分好几次加载。在用户拖动listview时再加载一定的数据,和sina微博的客户端类似。
给listview添加OnScrollListener监听事件默认会覆盖下面两个方法:

Java代码

1.new OnScrollListener() {
2. boolean isLastRow = false;
3.
4. @Override
5. public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
6. //滚动时一直回调,直到停止滚动时才停止回调。单击时回调一次。
7. //firstVisibleItem:当前能看见的第一个列表项ID(从0开始)
8. //visibleItemCount:当前能看见的列表项个数(小半个也算)
9. //totalItemCount:列表项共数
10.
11. //判断是否滚到最后一行
12. if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {
13. isLastRow = true;
14. }
15. }
16. @Override
17. public void onScrollStateChanged(AbsListView view, int scrollState) {
18. //正在滚动时回调,回调2-3次,手指没抛则回调2次。scrollState = 2的这次不回调
19. //回调顺序如下
20. //第1次:scrollState = SCROLL_STATE_TOUCH_SCROLL(1) 正在滚动
21. //第2次:scrollState = SCROLL_STATE_FLING(2) 手指做了抛的动作(手指离开屏幕前,用力滑了一下)
22. //第3次:scrollState = SCROLL_STATE_IDLE(0) 停止滚动
23.
24. //当滚到最后一行且停止滚动时,执行加载
25. if (isLastRow && scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
26. //加载元素
27. ......
28.
29. isLastRow = false;
30. }
31. }
32.}



一片国外的翻译文档,但是不是很正确
[url=]onScrollListener实施检测在ListView滚动年底[/url]
我ListView ListView显示一些项目。我想执行一些当前显示中的可见部分的项目ListView ListView,如何ListView中一直滚动,因此我认为OnScrollListener ListView ListView的。因此到Android API参考,onScroll法“将被称为滚动后已经完成”。这在我看来,我需要的东西,因为一旦滚动完成后,我在执行我的行动ListView (onScroll方法返回显示的第一项指数和显示的项目数)。
但是,一旦实施,我看到LogCat LogCat onScroll方法,不只是发射一次滚动已完成,但发射进入显示视图为每一个新项目,从开始到结束滚动。这不是我所期望的行为,也没有我需要的。 ,而不是其他的侦听器的方法(onScrollStateChanged)不提供有关在当前显示的项目的ListView ListView 。
所以,没有人知道如何使用这两个方法来检测滚动的结束,并得到所显示的项目信息?之间的API参考资料和实际行为的方法不对,弄得我有点。预先感谢。
PS:我已经看到了一些类似的主题周围,但没有帮助我了解整个事情的作品..!



[url=]回答[/url] [url=]1[/url] 为了获得这一行为向下是棘手的,我花了相当长一段时间来完善。肉的问题是,自己的滚动听众是不是真的很足以探测到一个“滚动停止”(包括方向键/轨迹球),至于我可以告诉。我结束了作品的权利,我希望它做的事情结合。
我想我能做到这一点的最好办法是延长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();} {stopWait();}}} / /所有这个等待可能得到改善,但是这想法私人主题waitThread = NULL;私人诠释waitCount = Integer.MIN_VALUE的;公共无效stopWait(){waitCount = Integer.MIN_VALUE的;}市民同步无效startWait(){waitCount = 0;(waitThread = NULL){;} waitThread =新主题(新的Runnable(){@覆盖公共无效的run() {尝试{(; waitCount.get()<10; waitCount + +){Thread.sleep代码(50);} / /踢它返回到UI线程view.post(theRunnableWithYourOnScrollStopCode); / /这里是你办什么你想要做关于停止}赶上(InterruptedException E){} {waitThread = NULL;}}}); waitThread.start();}请注意,您还可以customScrollListener customScrollListener在你的构造。这种实现是不错的,我觉得,因为它不会立即火“事件”,它会稍等一会,直到它实际上已经完全停止滚动。


[url=]2[/url] 在年底,我已经达到了一个解决方案,没有那么多优雅的,但为我工作;想通了,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! ***/ } } *** / 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)我保存的状态和我调用另一个方法,这实际上是了解是否有一个滚动的,如果它的完成。这样,我也有可见项目,我需要的数据。也许不干净,但作品!
关于



如果adapter中的数据量很大的时候,在加载listview时会出现卡顿的现象。这是会让用户抓狂!最好的解决办法就是先加载一定数量的数据,然后在最下方提示正在加载!  动态加载就是把放入adapter中的数据分好几次加载。在用户拖动listview时再加载一定的数据,和sina微博的客户端类似。
  给listview添加OnScrollListener监听事件默认会覆盖下面两个方法:
  Java代码 收藏代码
  OnScrollListener loadListener=new OnScrollListener() {
  @Override
  public void onScroll(AbsListView view, int firstVisibleItem,
  int visibleItemCount, int totalItemCount) {
  lastItem = firstVisibleItem + visibleItemCount;
  }
  @Override
  public void onScrollStateChanged(AbsListView view, int scrollState) {
  //listview滚动时会执行这个方法,这儿调用加载数据的方法。
  adapter.notifyDataSetChanged();//提醒adapter更新
  uList.setSelection(lastItem - 1);//设置listview的当前位置,如果不设置每次加载完后都会返回到list的第一项。
  }
  }
  };
  TIP:
  1、如果activity中只有listview,当listview的数据量很大时,在启动activity时会卡顿半天知道数据加载完可以显示,这时可以可以用handler,将加载数据的操作写在handler里面,而且要在onResume()方法中执行,放在onCreate()不起作用。
  2、如果是从网络获取数据,或者数据量很大可以新开一个线程,在线程中完成数据的加载。
  3、如果添加的加载提示框出不来,可能是加载过程一直占有cpu,无法显示提示框,可以将加载的代码写到handler里面,用postDelayed()方法给一定的时间延迟去加载数据。




监听ListView滚动到最底部

监听ListView的滚动可以用两个东西:
ListView.onScrollStateChanged (本文讲解这个listener的使用)
在OnGestureListener类里面的onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) 事件
SDK的Sample里面的ApiDemos里面的List9 和 List 13介绍了 ListView.OnScrollListener的使用。
List9介绍的是ListView.OnScrollListener的 onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) 方法。
List13介绍的是ListView.OnScrollListener的 onScrollStateChanged(AbsListView view, int scrollState) 方法,使用说明如下:
ListView.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { case OnScrollListener.SCROLL_STATE_IDLE: Log.v("已经停止:SCROLL_STATE_IDLE"); break; case OnScrollListener.SCROLL_STATE_FLING: Log.v("开始滚动:SCROLL_STATE_FLING"); break; case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: Log.v("正在滚动:SCROLL_STATE_TOUCH_SCROLL"); break; } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, inttotalItemCount) { }});

监听ListView滚动到最底部使用 onScrollStateChanged(AbsListView view, int scrollState) 方法,代码大致如下:
// 监听listview滚到最底部mIndexList.setOnScrollListener(new OnScrollListener() { @Override public voidonScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { // 当不滚动时 caseOnScrollListener.SCROLL_STATE_IDLE: // 判断滚动到底部 if (view.getLastVisiblePosition() == (view.getCount() - 1)) { isLastisNext++; } break; } } @Override public void onScroll(AbsListView view, intfirstVisibleItem, int visibleItemCount, int totalItemCount) { }});


我使用这个发现两个问题:
在模拟器上,如果使用鼠标的滚轮来滚动时执行 onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) 方法,不执行 onScrollStateChanged(AbsListView view, int scrollState) 方法。只有触摸往下滑动时,才执行onScrollStateChanged(AbsListView view, int scrollState) 方法。有待考证。
SCROLL_STATE_TOUCH_SCROLL一定执行,然后下面可能执行SCROLL_STATE_FLING,也可能执行SCROLL_STATE_IDLE。这个是不确定的。有待考证


package com.action;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.AbsListView.OnScrollListener;

public class ListViewActivity extends Activity {
private ListView lv;
private List list;
private int lastItem;
private int listSize;
private ListAdapter adapter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv = (ListView) findViewById(R.id.lv);
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, getData());
lv.setAdapter(adapter);
lv.setOnScrollListener(new OnScrollListener() {

@Override
public void onScrollStateChanged(AbsListView paramAbsListView, int paramInt) {
//当屏幕停止滚动时为0;当屏幕滚动且用户使用的触碰或手指还在屏幕上时为1;
//由于用户的操作,屏幕产生惯性滑动时为2
System.out.println("***lastItem:"+lastItem);
System.out.println("***listSize:"+listSize);
if(lastItem == listSize){
System.out.println("**************");
//数据全部显示出来时运行此处代码,如果要实现分页功能,在这里加载下一页的数据
}

}

@Override
public void onScroll(AbsListView paramAbsListView, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// // firstVisibleItem表示在现时屏幕第一个ListItem(部分显示的ListItem也算)
// // 在整个ListView的位置(下标从0开始)
// System.out.println("***firstParamInt:"+firstVisibleItem);
// // visibleItemCount表示在现时屏幕可以见到的ListItem(部分显示的ListItem也算)总数
// System.out.println("***visibleItemCount:"+visibleItemCount);
// // totalItemCount表示ListView的ListItem总数
// System.out.println("***totalItemCount:"+totalItemCount);
// listView.getLastVisiblePosition()表示在现时屏幕最后一个ListItem(最后ListItem要完全
// 显示出来才算)在整个ListView的位置(下标从0开始)
// System.out.println("****"+String.valueOf(lv.getLastVisiblePosition()));
lastItem = lv.getLastVisiblePosition();
}
});
}
private List getData(){
int i;
list = new ArrayList();
for(i=1; i<10; i++){
list.add("ListView"+i);
}
listSize = list.size()-1;
return list;
}
}

更多相关文章

  1. Android(安卓)自定义View onDraw方法详解
  2. android系统部分广播
  3. Android(安卓)混淆 Unknown verification type
  4. registerActivityLifecycleCallbacks 的用途
  5. Android(java):database disk image is malformed (code 11)
  6. android单元测试----junit
  7. Android(安卓)Studio无线调试app之Android(安卓)WiFi ADB
  8. java.lang.NoClassDefFoundError错误解决方法
  9. Android剪裁图片简单的方法

随机推荐

  1. 在android中利用多线程实现对控件的更新(
  2. 零基础入门Linux
  3. 使用科大讯飞提供的SDK实现android语音识
  4. Android集成Zxing实现二维码扫描识别,过程
  5. Android的Master/Detail风格界面中实现自
  6. 获取Android设备的唯一识别码|设备号|序号|U
  7. 【Android(安卓)开发教程】显示复杂对话
  8. Android学习笔记(十六)进度条
  9. Android应用框架之AndroidApplication
  10. Android(安卓)2.bootloader编译简析