Android中listView的下拉載入功能實現

來源:互聯網
上載者:User

標籤:

  • 今天給大家講講android開發中比較常見的listView的下拉載入,其實也可以叫做分頁載入。為什麼會有這個叫法呢?說說我的理解吧!

    • 從字面上很好理解。當你滑動一個列表到底部的時候,這個時候就會出現正在載入的底部載入布局去載入更多的資料。這裡拿作為一個例子,如所示:
    • 如所示紅色方框的部分就是底部的載入布局。從一定程度上這樣做是必要的,為了最佳化使用者的體驗。你可以想想,假如你點開的朋友圈的時候,如果沒有做分頁載入,那麼你需要等待很久的時間才能夠看到你和朋友發的一些狀態。這是因為這個時候代碼需要給伺服器發送請求擷取資料並呈現這些資料。這個時候擷取資料就成了最耗時的問題。為什麼這麼說?如果沒有分頁載入的功能,那麼,你肯定需要擷取全部的資料,你可以想想,好幾年的資料,資料量可不少啊!發請求去擷取這些資料並呈現它們是會很耗時間的。所以分頁載入就很好的解決了這個問題。你先擷取其中的十幾條資料並呈現它們。當你一直從頭瀏覽這十幾條資料到結束的時候,這個時候再去載入更多的資料並呈現它們。如所示,這樣才是好的使用者體驗。

  • 概念清晰後,具體實現的部分到了。這裡實現的下拉載入效果(個人感覺很不錯,簡潔明了),大概需要以下幾個步驟:
    • first — 首先構建下拉載入時的底部載入布局(這裡命名為view_more)
    • second — 擷取資料並給listView設定adapter;設定好adapter後,調用方法:listView.addFooterView(view_more);// TODO 添加底部記載布局再往listView的底部添加底部載入布局。最後對listView設定滑動監聽器:listView.setOnScrollListener(this);// TODO listView這是滑動監聽 並重寫相關方法:
      public void onScrollStateChanged(AbsListView view, int scrollState) {}public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {} 這兩個重寫的方法一個是監聽listView的滑動狀態改變,另一個是監聽listView的滑動。
    • third — 當滑動監聽設定好後,在重寫的兩個方法裡面判斷listView是否滑動到底部並且停止滑動(即滑動狀態為停止滑動)。如果此時滿足這個條件,那麼就載入更多的資料。資料載入完成後就重新整理資料來源,此時會有更多的資料在底部出現。
    • fourth — 最後當資料全部載入好後,移除第二步中添加的底部載入布局view_more,調用方法:listView.removeFooterView(view_more);// TODO 移除底部的載入布局
下面寫代碼一步一步來實現:
  • 1、首先準備一個底部載入布局,命名為view_more
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="80dp"    android:background="#8888" >    <TextView        android:id="@+id/tv_Load"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:text="正在載入..."        android:textSize="14sp"        android:visibility="visible" />    <ProgressBar        android:id="@+id/progressBar"        style="?android:attr/progressBarStyleSmall"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerVertical="true"        android:layout_toLeftOf="@id/tv_Load"        android:padding="10dp"        android:visibility="visible" /></RelativeLayout>

很簡單的布局,顯示了一個進度條和一個文本控制項。

  • 第二,給listView設定資料並設定滑動監聽,設定好後判斷是否滑動到listView的底部並停止滑動,如果是那麼載入更多的資料:
package com.example.drop_down_load;import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.View;import android.widget.AbsListView;import android.widget.AbsListView.OnScrollListener;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.TextView;public class MainActivity extends Activity implements OnScrollListener {    private ListView listView;    private int totalCount;// 資料總條數    private List<String> lists = new ArrayList<String>();    private ArrayAdapter<String> adapter;    // 建立handler接收訊息並處理訊息    private Handler handler = new Handler() {        public void handleMessage(android.os.Message msg) {            switch (msg.what) {            case 0:                // 建立adapter                adapter = new ArrayAdapter<String>(MainActivity.this,                        android.R.layout.simple_list_item_1, lists);                // 設定adapter                listView.setAdapter(adapter);                // 添加底部載入布局                listView.addFooterView(view_more);                // 設定監聽                setListeners();                break;            }        };    };    private View view_more;    private ProgressBar pb;    private TextView tvLoad;    private int lastVisibleIndex;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // 控制項初始化        initViews();        // 初始化資料        initData();    }    private void initData() {        // 類比網路請求擷取資料,一次擷取15條        new Thread() {            public void run() {                try {                    totalCount = 100;// 假設資料一共有100條,將來調介面可以擷取到這個值                    for (int i = 0; i < 15; i++) {                        lists.add("資料" + (i + 1));                    }                    // 給handler發訊息更新UI,子線程不可以更新UI                    Message message = new Message();                    message.what = 0;                    handler.sendMessage(message);                } catch (Exception e) {                    e.printStackTrace();                }            };        }.start();    }    private void setListeners() {        if (totalCount > 15) {            // listView設定滑動簡監聽            listView.setOnScrollListener(this);        } else {            // 假如資料總數少於等於15條,直接移除底部的載入布局,不需要再載入更多的資料            listView.removeFooterView(view_more);        }    }    private void initViews() {        listView = (ListView) findViewById(R.id.listView);        // 構建底部載入布局        view_more = (View) getLayoutInflater()                .inflate(R.layout.view_more, null);        // 進度條        pb = (ProgressBar) view_more.findViewById(R.id.progressBar);        // “正在載入...”文本控制項        tvLoad = (TextView) view_more.findViewById(R.id.tv_Load);    }    /**     * 監聽listView的滑動狀態的改變     */    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {        Log.e("TAG", "lastVisibleIndex = " + lastVisibleIndex);        Log.e("TAG", "adapter.getCount() = " + adapter.getCount());        // 滑到底部後自動載入,判斷listView已經停止滾動並且最後可視的條目等於adapter的條目        // 注意這裡在listView設定好adpter後,加了一個底部載入布局。        // 所以判斷條件為:lastVisibleIndex == adapter.getCount()        if (scrollState == SCROLL_STATE_IDLE                && lastVisibleIndex == adapter.getCount()) {            /**             * 這裡也要設定為可見,是因為當你真正從網路擷取資料且擷取失敗的時候。             * 我在失敗的方法裡面,隱藏了底部的載入布局並提示使用者載入失敗。所以再次監聽的時候需要             * 繼續顯示隱藏的控制項。因為我類比的擷取資料,失敗的情況這裡不給出。實際中簡單的加上幾句代碼就行了。             */            pb.setVisibility(View.VISIBLE);            tvLoad.setVisibility(View.VISIBLE);            loadMoreData();// 載入更多資料        }    }    private void loadMoreData() {    }    /**     * 監聽listView的滑動     */    @Override    public void onScroll(AbsListView view, int firstVisibleItem,            int visibleItemCount, int totalItemCount) {        // 計算最後可見條目的索引        lastVisibleIndex = firstVisibleItem + visibleItemCount - 1;        // 當adapter中的所有條目數已經和要載入的資料總條數相等時,則移除底部的View        if (totalItemCount == totalCount + 1) {            // 移除底部的載入布局            listView.removeFooterView(view_more);        }    }}

以上代碼就是我上面步驟2和步驟2中所說的東西。加上我寫了注釋,所以相信大家看起來很簡單。關鍵點是怎麼判斷listView是否滑動到了底部並停止了滑動。我在代碼中添加了兩行log,可以列印日誌資訊。大家去自己調試就能明白我對關鍵點是怎麼判斷的了,但是也有聰明的!嘿嘿!大家都懂,自己人,我就不接話了。

  • 最後就是載入更多的資料了,即完成第二步中未完成的方法:
loadMoreData();// 載入更多資料

具體代碼實現為:

private void loadMoreData() {        // 擷取此時adapter中的總條目數        int count = adapter.getCount();        // 一次載入15條資料,即下拉載入的執行        if (count + 15 < totalCount) {            start = count;            end = start + 15;            initData(start, end);// 類比網路擷取資料操作        } else {// 資料不足15條直接載入到結束            start = count;            end = totalCount;            initData(start, end);// 類比網路擷取資料曹祖            // 資料全部載入完成後,移除底部的view            listView.removeFooterView(view_more);            Toast.makeText(MainActivity.this, "資料已經全部載入", 1).show();        }    }private void initData(final int start, final int end) {        // 類比網路請求擷取資料,一次擷取15條        new Thread() {            public void run() {                try {                    Thread.sleep(4000);// 類比擷取資料時的耗時3s                    for (int i = start; i < end; i++) {                        lists.add(i, "資料" + (i + 1));                    }                    // 給handler發訊息更新UI,子線程不可以更新UI                    Message message = new Message();                    message.what = 1;                    handler.sendMessage(message);                } catch (Exception e) {                    e.printStackTrace();                }            };        }.start();    }

此時handler中還要再加一個case語句,用來重新整理資料來源,紅色方框標註地方,大家自己加一下。最後我會給項目源碼,大家可以下載看My Code:

好了下面給出幾張項目的展示圖片:

  • 15條資料後載入更多資料,

  • 30條資料後載入更多資料,

  • 45條資料後載入更多資料,

  • 資料全部載入完後,移除底部載入布局,

談談我的感悟:你需要有自己的想法思路,別人的東西可以借鑒,但是你需要從中學到點什麼。要是什麼都沒學到,那就失去了分享的意義了!分享是為了讓大家學到更多,收穫更多。希望我的這篇能夠給大家一點點收穫!

項目的源碼:點擊我下載項目源碼

每天進步一點點!加油!

Android中listView的下拉載入功能實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.