android UI進階之實現listview的分頁加載

當用戶從網絡上讀取微薄的時候,若是一會兒所有加載用戶未讀的微薄這將耗費比較長的時間,形成很差的用戶體驗,同時一屏的內容也不足以顯示如此多的內容。這時候,咱們就須要用到另外一個功能,那就是listview的分頁了。經過分頁分次加載數據,用戶看多少就去加載多少。
一般這也分爲兩種方式,一種是設置一個按鈕,用戶點擊即加載。另外一種是當用戶滑動到底部時自動加載。今天我就和你們分享一下這個功能的實現。
首先,寫一個xml文件,moredata.xml,該文件即定義了放在listview底部的視圖:
<? xml version ="1.0" encoding ="utf-8" ?>
< LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android"
         android:layout_width ="match_parent"
         android:layout_height ="match_parent"
         android:orientation ="vertical" >
     < Button        
             android:id ="@+id/bt_load"        
             android:layout_width ="fill_parent"        
             android:layout_height ="wrap_content"    
             android:text ="加載更多數據" />    
     < ProgressBar
             android:id ="@+id/pg"
             android:layout_width ="wrap_content"
             android:layout_height ="wrap_content"
             android:layout_gravity ="center_horizontal"
             android:visibility ="gone"
             />
</ LinearLayout >
 
能夠看到是一個按鈕和一個進度條。由於只作一個演示,這裏簡單處理,經過設置控件的visibility,未加載時顯示按鈕,加載時就顯示進度條。
寫一個item.xml,你們應該很熟悉了。用來定義listview的每一個item的視圖。
 
<? xml version ="1.0" encoding ="utf-8" ?>
< LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android"
         android:layout_width ="match_parent"
         android:layout_height ="match_parent"
         android:orientation ="vertical" >
        
         < TextView
                 android:id ="@+id/tv_title"
                 android:textSize ="20sp"
                 android:layout_width ="wrap_content"
                 android:layout_height ="wrap_content"
                 android:layout_marginTop ="5dp"
                 />
         < TextView
                 android:textSize ="12sp"
                 android:id ="@+id/tv_content"
                 android:layout_width ="wrap_content"
                 android:layout_height ="wrap_content"
                 android:layout_marginTop ="5dp"
                 />

</ LinearLayout >
 
 
main.xml就不貼了,整個主界面就一個listview。
直接先看下Activity的代碼,在裏面實現分頁效果。
 
package com.notice.moredate;

import java.util.ArrayList;
import java.util.HashMap;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import android.widget.Toast;

public class MoreDateListActivity extends Activity implements OnScrollListener {
        
         // ListView的Adapter
         private SimpleAdapter mSimpleAdapter;
         private ListView lv;
         private Button bt;
         private ProgressBar pg;
         private ArrayList<HashMap<String,String>> list;
         // ListView底部View
         private View moreView;
         private Handler handler;
         // 設置一個最大的數據條數,超過即再也不加載
         private int MaxDateNum;
         // 最後可見條目的索引
         private int lastVisibleIndex;
        
         /** Called when the activity is first created. */
        @Override
         public void onCreate(Bundle savedInstanceState) {
                 super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                
                
                MaxDateNum = 22; // 設置最大數據條數

                lv = (ListView) findViewById(R.id.lv);

                 // 實例化底部佈局
                moreView = getLayoutInflater().inflate(R.layout.moredate, null);

                bt = (Button) moreView.findViewById(R.id.bt_load);
                pg = (ProgressBar) moreView.findViewById(R.id.pg);
                handler = new Handler();

                 // 用map來裝載數據,初始化10條數據
                list = new ArrayList<HashMap<String,String>>();
                 for ( int i = 0; i < 10; i++) {
                        HashMap<String, String> map = new HashMap<String, String>();
                        map.put( "ItemTitle", "第" + i + "行標題");
                        map.put( "ItemText", "第" + i + "行內容");
                        list.add(map);
                }
                 // 實例化SimpleAdapter
                mSimpleAdapter = new SimpleAdapter( this, list, R.layout.item,
                                 new String[] { "ItemTitle", "ItemText" },
                                 new int[] { R.id.tv_title, R.id.tv_content });
                 // 加上底部View,注意要放在setAdapter方法前
                lv.addFooterView(moreView);
                lv.setAdapter(mSimpleAdapter);
                 // 綁定監聽器
                lv.setOnScrollListener( this);

                bt.setOnClickListener( new OnClickListener() {

                        @Override
                         public void onClick(View v) {
                                pg.setVisibility(View.VISIBLE); // 將進度條可見
                                bt.setVisibility(View.GONE); // 按鈕不可見

                                handler.postDelayed( new Runnable() {

                                        @Override
                                         public void run() {
                                                loadMoreDate(); // 加載更多數據
                                                bt.setVisibility(View.VISIBLE);
                                                pg.setVisibility(View.GONE);
                                                mSimpleAdapter.notifyDataSetChanged(); // 通知listView刷新數據
                                        }

                                }, 2000);
                        }
                });

        }

         private void loadMoreDate() {
                 int count = mSimpleAdapter.getCount();
                 if (count + 5 < MaxDateNum) {
                         // 每次加載5條
                         for ( int i = count; i < count + 5; i++) {
                                HashMap<String, String> map = new HashMap<String, String>();
                                map.put( "ItemTitle", "新增第" + i + "行標題");
                                map.put( "ItemText", "新增第" + i + "行內容");
                                list.add(map);
                        }
                } else {
                         // 數據已經不足5條
                         for ( int i = count; i < MaxDateNum; i++) {
                                HashMap<String, String> map = new HashMap<String, String>();
                                map.put( "ItemTitle", "新增第" + i + "行標題");
                                map.put( "ItemText", "新增第" + i + "行內容");
                                list.add(map);
                        }
                }

        }

        @Override
         public void onScroll(AbsListView view, int firstVisibleItem,
                         int visibleItemCount, int totalItemCount) {
                 // 計算最後可見條目的索引
                lastVisibleIndex = firstVisibleItem + visibleItemCount - 1;

                 // 全部的條目已經和最大條數相等,則移除底部的View
                 if (totalItemCount == MaxDateNum + 1) {
                        lv.removeFooterView(moreView);
                        Toast.makeText( this, "數據所有加載完成,沒有更多數據!", Toast.LENGTH_LONG).show();
                }

        }

        @Override
         public void onScrollStateChanged(AbsListView view, int scrollState) {
                 // 滑到底部後自動加載,判斷listview已經中止滾動而且最後可視的條目等於adapter的條目
                 if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
                                && lastVisibleIndex == mSimpleAdapter.getCount()) {
                         // 當滑到底部時自動加載
                         // pg.setVisibility(View.VISIBLE);
                         // bt.setVisibility(View.GONE);
                         // handler.postDelayed(new Runnable() {
                         //
                         // @Override
                         // public void run() {
                         // loadMoreDate();
                         // bt.setVisibility(View.VISIBLE);
                         // pg.setVisibility(View.GONE);
                         // mSimpleAdapter.notifyDataSetChanged();
                         // }
                         //
                         // }, 2000);

                }

        }
        
}
 
 
 
經過註釋,你們應該很容易理解了。這裏作下簡單的解析。首先要注意的是,addFootView方法必定要在setAdapter方法以前,不然會無效。addFootView方法爲listview底部加入一個視圖,在本例中就是那個Button加progressbar的視圖。當用戶點擊按鈕時,調用loadmoreDate方法,爲listview綁定更多的數據,經過adapter的notifyDataSetChanged方法通知listview刷新,顯示剛加入的數據。
這裏用handler異步延遲2秒操做,模仿加載過程。同時listview綁定了onScrollListener監聽器,而且實現了onScroll和onScrollStateChanged方法。在後者方法中,咱們經過判斷listview已經中止滾動而且最後可視的條目等於adapter的條目,能夠知道用戶已經滑動到底部而且自動加載,代碼中將這部分代碼註釋掉了,你們能夠本身試下。
代碼中還加入了一個MaxDateNum變量,用來記錄最大的數據數量。也就是說網絡或者其餘地方一共的數據。經過onScroll方法判斷用戶加載完這些數據後,移除listview底部視圖,不讓繼續加載。同時在loadmoreDate方法中也對最大數據量作相應的操做來判斷加載數量。(默認加載5條,不足5條時加載剩餘的)。
看下效果圖:
 
 
 
 
相關文章
相關標籤/搜索