實現ListView的分頁加載功能php
2012年02月13日 ⁄ Android 編程 ⁄ 暫無評論 ⁄ 被圍觀 6,215 次+html
![ListView_Page 若水工做室](http://static.javashuo.com/static/loading.gif)
上圖是一個新聞客戶端的顯示界面,新聞的信息是顯示在ListView的控件中,咱們知道要顯示的新聞會不少,咱們不可能每次都加載進來,所以咱們這時須要進行分頁處理。java
一般這也分爲兩種方式,一種是設置一個按鈕,用戶點擊即加載,如上圖。另外一種是當用戶滑動到底部時自動加載。今天就和你們分享一下這個功能的實現。android
首先,寫一個xml文件,moredata.xml,該文件即定義了放在listview底部的視圖,如上圖的「加載更多」按鈕:編程
查看源代碼 打印 幫助 網絡
1 |
<? xml version = "1.0" encoding = "utf-8" ?> |
3 |
android:layout_width = "match_parent" |
4 |
android:layout_height = "match_parent" |
5 |
android:orientation = "vertical" > |
7 |
android:id = "@+id/bt_load" |
8 |
android:layout_width = "fill_parent" |
9 |
android:layout_height = "wrap_content" |
10 |
android:text = "加載更多據" /> |
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" |
很簡單的XML文件,一個按鈕和一個進度條。由於只作一個演示,這裏簡單處理,經過設置控件的visibility,未加載時顯示按鈕,加載時就顯示進度條。app
寫一個item.xml,用來定義listview的每一個item的視圖:異步
查看源代碼 打印 幫助 ide
1 |
<? xml version = "1.0" encoding = "utf-8" ?> |
3 |
android:layout_width = "match_parent" |
4 |
android:layout_height = "match_parent" |
5 |
android:orientation = "vertical" > |
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" |
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" |
MainActivity的頁面佈局XML,main.xml:佈局
查看源代碼 打印 幫助
1 |
<? xml version = "1.0" encoding = "utf-8" ?> |
3 |
android:layout_width = "fill_parent" |
4 |
android:layout_height = "fill_parent" |
5 |
android:orientation = "vertical" > |
8 |
android:layout_width = "fill_parent" |
9 |
android:layout_height = "fill_parent" |
下面咱們看下MainActivity代碼,在裏面實現分頁效果:
查看源代碼 打印 幫助
1 |
package com.szy.listviewdemo; |
3 |
import java.util.ArrayList; |
4 |
import java.util.HashMap; |
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; |
24 |
public class MainActivity extends Activity implements OnScrollListener |
27 |
private SimpleAdapter simpleAdapter; |
30 |
private ProgressBar progressBar; |
31 |
private ArrayList<HashMap<String, String>> list; |
33 |
private View moreView; |
34 |
private Handler handler; |
35 |
// 設置一個最大的數據條數,超過即再也不加載 |
36 |
private int MaxDateNum; |
38 |
private int lastVisibleIndex; |
41 |
public void onCreate(Bundle savedInstanceState) |
43 |
super .onCreate(savedInstanceState); |
44 |
setContentView(R.layout.main); |
45 |
MaxDateNum = 22 ; // 設置最大數據條數 |
46 |
lv = (ListView) findViewById(R.id.lv); |
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(); |
53 |
list = new ArrayList<HashMap<String, String>>(); |
54 |
for ( int i = 0 ; i < 10 ; i++) |
56 |
HashMap<String, String> map = new HashMap<String, String>(); |
57 |
map.put( "itemTitle" , "第" + i + "行標題" ); |
58 |
map.put( "itemText" , "第" + i + "行內容" ); |
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); |
70 |
lv.setOnScrollListener( this ); |
71 |
btn.setOnClickListener( new OnClickListener() |
74 |
public void onClick(View v) |
76 |
progressBar.setVisibility(View.VISIBLE); // 將進度條可見 |
77 |
btn.setVisibility(View.GONE); // 按鈕不可見 |
78 |
handler.postDelayed( new Runnable() |
83 |
loadMoreDate(); // 加載更多數據 |
84 |
btn.setVisibility(View.VISIBLE); |
85 |
progressBar.setVisibility(View.GONE); |
86 |
simpleAdapter.notifyDataSetChanged(); // 通知listView刷新數據 |
95 |
private void loadMoreDate() |
97 |
int count = simpleAdapter.getCount(); |
98 |
if (count + 5 < MaxDateNum) |
101 |
for ( int i = count; i < count + 5 ; i++) |
103 |
HashMap<String, String> map = new HashMap<String, String>(); |
104 |
map.put( "itemTitle" , "新增第" + i + "行標題" ); |
105 |
map.put( "itemText" , "新增第" + i + "行內容" ); |
111 |
for ( int i = count; i < MaxDateNum; i++) |
113 |
HashMap<String, String> map = new HashMap<String, String>(); |
114 |
map.put( "itemTitle" , "新增第" + i + "行標題" ); |
115 |
map.put( "itemText" , "新增第" + i + "行內容" ); |
123 |
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) |
126 |
lastVisibleIndex = firstVisibleItem + visibleItemCount - 1 ; |
127 |
// 全部的條目已經和最大條數相等,則移除底部的View |
128 |
if (totalItemCount == MaxDateNum + 1 ) |
130 |
lv.removeFooterView(moreView); |
131 |
Toast.makeText( this , "數據所有加載完成,沒有更多數據!" , Toast.LENGTH_LONG).show(); |
136 |
public void onScrollStateChanged(AbsListView view, int scrollState) |
138 |
// 滑到底部後自動加載,判斷listview已經中止滾動而且最後可視的條目等於adapter的條目 |
139 |
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE && lastVisibleIndex == simpleAdapter.getCount()) |
142 |
// progressBar.setVisibility(View.VISIBLE); |
143 |
// btn.setVisibility(View.GONE); |
144 |
// handler.postDelayed(new Runnable() { |
147 |
// public void run() { |
149 |
// btn.setVisibility(View.VISIBLE); |
150 |
// progressBar.setVisibility(View.GONE); |
151 |
// simpleAdapter.notifyDataSetChanged(); |
經過註釋,你們應該很容易理解了。這裏作下簡單的解析。首先要注意的是,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條時加載剩餘的)。
看下效果圖:
![ListView_Page_1 若水工做室](http://static.javashuo.com/static/loading.gif)
![ListView_Page_2 若水工做室](http://static.javashuo.com/static/loading.gif)
示例代碼下載地址:
http://115.com/file/c2dfxva5
昨天我也遇到這個問題,也在網上查找了不少資料,大概有兩種方案,一種就是自定義GridView,就是extends它,或者extends RelativeLayout,而後本身實現它。網上能找出來的資料基本上都是這種。還有一種方案,用ListView來實現。假設你的GridView有3列,假如是三張ImageView吧,那你在自定義ListView的Item的時候,就得有3個ImageView。固然還得修改Adapter中的getCount方法,相似於這樣:
- public int getCount() {
- if (photos.size() % 3 == 0) {
- return photos.size() / 3;
- }
- return photos.size() / 3 + 1;
- }
而後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的數據,也就能夠向其它頁面傳數據了。
大概原理是這樣,我這項目裏面還有動態選中和批量刪除功能。代碼量比較大,就不貼了,有什麼問題再問吧。我這裏測試工程裏面的效果以下所示,看看是否是你須要的。
![請輸入圖片描述](http://static.javashuo.com/static/loading.gif)