官方文档:http://developer.android.com/ref ... ScrollListener.html
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<String> 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<String>(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<String> getData(){
int i;
list = new ArrayList<String>();
for(i=1; i<10; i++){
list.add("ListView"+i);
}
listSize = list.size()-1;
return list;
}
}
如果还有什么不懂的,见意去看下源码。
一片国外的翻译文档,但是不是很正确
[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的滚动可以用两个东西:
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, int totalItemCount) {
}
});
监听ListView滚动到最底部使用 onScrollStateChanged(AbsListView view, int scrollState) 方法,代码大致如下:
// 监听listview滚到最底部
mIndexList.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) { // 当不滚动时
case OnScrollListener.SCROLL_STATE_IDLE: // 判断滚动到底部
if (view.getLastVisiblePosition() == (view.getCount() - 1)) {
isLastisNext++;
}
break;
}
}
@Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
我使用这个发现两个问题: