ListViewOnScrollListener詳解(滑屏分頁顯示數據)

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;    }} 若是還有什麼不懂的,見意去看下源碼。
              
  

OnScrollListener回調分析html




若是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:
  一、若是activity中只有listview,當listview的數據量很大時,在啓動activity時會卡頓半天知道數據加載完能夠顯示,這時能夠能夠用handler,將加載數據的操做寫在handler裏面,並且要在onResume()方法中執行,放在onCreate()不起做用。
  二、若是是從網絡獲取數據,或者數據量很大能夠新開一個線程,在線程中完成數據的加載。
  三、若是添加的加載提示框出不來,多是加載過程一直佔有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, intscrollState) {        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 voidonScrollStateChanged(AbsListView view, int scrollState) {        switch (scrollState) {            // 當不滾動時            caseOnScrollListener.SCROLL_STATE_IDLE:                // 判斷滾動到底部                if (view.getLastVisiblePosition() == (view.getCount() - 1)) {                    isLastisNext++;              }              break;        }    }     @Override    public voidonScroll(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。這個是不肯定的。有待考證。
相關文章
相關標籤/搜索