實現ListView的分頁加載功能

實現ListView的分頁加載功能php

2012年02月13日 ⁄ Android 編程暫無評論 ⁄ 被圍觀 6,215 次+html

若水工做室

上圖是一個新聞客戶端的顯示界面,新聞的信息是顯示在ListView的控件中,咱們知道要顯示的新聞會不少,咱們不可能每次都加載進來,所以咱們這時須要進行分頁處理。java

一般這也分爲兩種方式,一種是設置一個按鈕,用戶點擊即加載,如上圖。另外一種是當用戶滑動到底部時自動加載。今天就和你們分享一下這個功能的實現。android

首先,寫一個xml文件,moredata.xml,該文件即定義了放在listview底部的視圖,如上圖的「加載更多」按鈕:編程

查看源代碼     打印     幫助 網絡

1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3     android:layout_width="match_parent"
4     android:layout_height="match_parent"
5     android:orientation="vertical" >
6   <Button   
7       android:id="@+id/bt_load"   
8       android:layout_width="fill_parent"   
9       android:layout_height="wrap_content" 
10       android:text="加載更多據" />
11   <ProgressBar
12       android:id="@+id/progressBar"
13       android:layout_width="wrap_content"
14       android:layout_height="wrap_content"
15       android:layout_gravity="center_horizontal"
16       android:visibility="gone"
17       />
18 </LinearLayout>

很簡單的XML文件,一個按鈕和一個進度條。由於只作一個演示,這裏簡單處理,經過設置控件的visibility,未加載時顯示按鈕,加載時就顯示進度條。app

寫一個item.xml,用來定義listview的每一個item的視圖:異步

查看源代碼     打印     幫助 ide

1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3     android:layout_width="match_parent"
4     android:layout_height="match_parent"
5     android:orientation="vertical" >
6     <TextView
7         android:id="@+id/tv_title"
8         android:textSize="20sp"
9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:layout_marginTop="5dp"
12         />
13     <TextView
14         android:textSize="12sp"
15         android:id="@+id/tv_content"
16         android:layout_width="wrap_content"
17         android:layout_height="wrap_content"
18         android:layout_marginTop="5dp"
19         />
20 </LinearLayout>

MainActivity的頁面佈局XML,main.xml:佈局

查看源代碼     打印     幫助

1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3     android:layout_width="fill_parent"
4     android:layout_height="fill_parent"
5     android:orientation="vertical" >
6     <ListView
7         android:id="@+id/lv"
8         android:layout_width="fill_parent"
9         android:layout_height="fill_parent"
10     />
11 </LinearLayout>

下面咱們看下MainActivity代碼,在裏面實現分頁效果:

查看源代碼     打印     幫助

1 package com.szy.listviewdemo;
2   
3 import java.util.ArrayList;
4 import java.util.HashMap;
5   
6 import android.app.Activity;
7 import android.os.Bundle;
8 import android.os.Handler;
9 import android.view.View;
10 import android.view.View.OnClickListener;
11 import android.widget.AbsListView;
12 import android.widget.AbsListView.OnScrollListener;
13 import android.widget.Button;
14 import android.widget.ListView;
15 import android.widget.ProgressBar;
16 import android.widget.SimpleAdapter;
17 import android.widget.Toast;
18   
19 /**
20  * @author  coolszy
21  * @date 2012-2-10
22  * @blog  http://blog.92coding.com
23  */
24 public class MainActivity extends Activity implements OnScrollListener
25 {
26   
27  private SimpleAdapter simpleAdapter;
28  private ListView lv;
29  private Button btn;
30  private ProgressBar progressBar;
31  private ArrayList<HashMap<String, String>> list;
32  // ListView底部View
33  private View moreView;
34  private Handler handler;
35  // 設置一個最大的數據條數,超過即再也不加載
36  private int MaxDateNum;
37  // 最後可見條目的索引
38  private int lastVisibleIndex;
39   
40  @Override
41  public void onCreate(Bundle savedInstanceState)
42  {
43   super.onCreate(savedInstanceState);
44   setContentView(R.layout.main);
45   MaxDateNum = 22; // 設置最大數據條數
46   lv = (ListView) findViewById(R.id.lv);
47   // 實例化底部佈局
48   moreView = getLayoutInflater().inflate(R.layout.moredata, null);
49   btn = (Button) moreView.findViewById(R.id.bt_load);
50   progressBar = (ProgressBar) moreView.findViewById(R.id.progressBar);
51   handler = new Handler();
52   //初始化10條數據
53   list = new ArrayList<HashMap<String, String>>();
54   for (int i = 0; i < 10; i++)
55   {
56    HashMap<String, String> map = new HashMap<String, String>();
57    map.put("itemTitle", "第" + i + "行標題");
58    map.put("itemText", "第" + i + "行內容");
59    list.add(map);
60   }
61   // 實例化SimpleAdapter
62   simpleAdapter = new SimpleAdapter(this, list, R.layout.item, new String[]
63    { "itemTitle", "itemText" }, new int[]
64    { R.id.tv_title, R.id.tv_content });
65   // 加上底部View,注意要放在setAdapter方法前
66   lv.addFooterView(moreView);
67   lv.setAdapter(simpleAdapter);
68     
69   // 綁定監聽器
70   lv.setOnScrollListener(this);
71   btn.setOnClickListener(new OnClickListener()
72   {
73    @Override
74    public void onClick(View v)
75    {
76     progressBar.setVisibility(View.VISIBLE);// 將進度條可見
77     btn.setVisibility(View.GONE);// 按鈕不可見
78     handler.postDelayed(new Runnable()
79     {
80      @Override
81      public void run()
82      {
83       loadMoreDate();// 加載更多數據
84       btn.setVisibility(View.VISIBLE);
85       progressBar.setVisibility(View.GONE);
86       simpleAdapter.notifyDataSetChanged();// 通知listView刷新數據
87      }
88   
89     }, 2000);
90    }
91   });
92   
93  }
94   
95  private void loadMoreDate()
96  {
97   int count = simpleAdapter.getCount();
98   if (count + 5 < MaxDateNum)
99   {
100    // 每次加載5條
101    for (int i = count; i < count + 5; i++)
102    {
103     HashMap<String, String> map = new HashMap<String, String>();
104     map.put("itemTitle", "新增第" + i + "行標題");
105     map.put("itemText", "新增第" + i + "行內容");
106     list.add(map);
107    }
108   } else
109   {
110    // 數據已經不足5條
111    for (int i = count; i < MaxDateNum; i++)
112    {
113     HashMap<String, String> map = new HashMap<String, String>();
114     map.put("itemTitle", "新增第" + i + "行標題");
115     map.put("itemText", "新增第" + i + "行內容");
116     list.add(map);
117    }
118   }
119   
120  }
121   
122  @Override
123  public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
124  {
125   // 計算最後可見條目的索引
126   lastVisibleIndex = firstVisibleItem + visibleItemCount - 1;
127   // 全部的條目已經和最大條數相等,則移除底部的View
128   if (totalItemCount == MaxDateNum + 1)
129   {
130    lv.removeFooterView(moreView);
131    Toast.makeText(this, "數據所有加載完成,沒有更多數據!", Toast.LENGTH_LONG).show();
132   }
133  }
134   
135  @Override
136  public void onScrollStateChanged(AbsListView view, int scrollState)
137  {
138   // 滑到底部後自動加載,判斷listview已經中止滾動而且最後可視的條目等於adapter的條目
139   if (scrollState == OnScrollListener.SCROLL_STATE_IDLE && lastVisibleIndex == simpleAdapter.getCount())
140   {
141    // 當滑到底部時自動加載
142    // progressBar.setVisibility(View.VISIBLE);
143    // btn.setVisibility(View.GONE);
144    // handler.postDelayed(new Runnable() {
145    //
146    // @Override
147    // public void run() {
148    // loadMoreDate();
149    // btn.setVisibility(View.VISIBLE);
150    // progressBar.setVisibility(View.GONE);
151    // simpleAdapter.notifyDataSetChanged();
152    // }
153    //
154    // }, 2000);
155   }
156  }
157 }

經過註釋,你們應該很容易理解了。這裏作下簡單的解析。首先要注意的是,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條時加載剩餘的)。

看下效果圖:

若水工做室

若水工做室

示例代碼下載地址:

http://115.com/file/c2dfxva5

 

 

 

 

 

昨天我也遇到這個問題,也在網上查找了不少資料,大概有兩種方案,一種就是自定義GridView,就是extends它,或者extends RelativeLayout,而後本身實現它。網上能找出來的資料基本上都是這種。還有一種方案,用ListView來實現。假設你的GridView有3列,假如是三張ImageView吧,那你在自定義ListView的Item的時候,就得有3個ImageView。固然還得修改Adapter中的getCount方法,相似於這樣:

   
     
  1. public int getCount() { 
  2.     if (photos.size() % 3 == 0) { 
  3.         return photos.size() / 3; 
  4.     } 
  5.     return photos.size() / 3 + 1; 
  6. }

而後getView也會有相應的修改,無非就是根據position來計算吧,這裏給個公式:當前行的第一個ImageView的位置是position3,第二個ImageView是position3+1,第三個是position*3+2

而後爲每一個ImageView設置onClickListener監聽,這個能夠從自定義的Adapter的構造方法中傳過來。由於要取得當前點擊的某個ImageView的數據,因此給每一個ImageView設置一個Tag對象,這裏直接把當前的Photo設置給ImageView的Tag。這裏,在onClick(View v)中,經過Photo photp = v.getTag()就能夠取得當前所點擊的ImageView的數據,也就能夠向其它頁面傳數據了。
大概原理是這樣,我這項目裏面還有動態選中和批量刪除功能。代碼量比較大,就不貼了,有什麼問題再問吧。我這裏測試工程裏面的效果以下所示,看看是否是你須要的。

請輸入圖片描述

相關文章
相關標籤/搜索