实现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的数据,也就能够向其它页面传数据了。
大概原理是这样,我这项目里面还有动态选中和批量删除功能。代码量比较大,就不贴了,有什么问题再问吧。我这里测试工程里面的效果以下所示,看看是否是你须要的。

请输入图片描述

相关文章
相关标签/搜索