官方文檔: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;
}
}
如果還有什麼不懂的,見意去看下源碼。
如果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, 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) {
}
});
我使用這個發現兩個問題:
- 在模擬器上,如果使用鼠標的滾輪來滾動時執行 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。這個是不確定的。有待考證。