文档章节

实现ListView的分页加载功能

 等待流星
发布于 2014/04/08 14:50
字数 1969
阅读 173
收藏 6

实现ListView的分页加载功能

2012年02月13日 ⁄ Android 编程暂无评论 ⁄ 被围观 6,215 次+

若水工作室

上图是一个新闻客户端的显示界面,新闻的信息是显示在ListView的控件中,我们知道要显示的新闻会很多,我们不可能每次都加载进来,因此我们这时需要进行分页处理。

通常这也分为两种方式,一种是设置一个按钮,用户点击即加载,如上图。另一种是当用户滑动到底部时自动加载。今天就和大家分享一下这个功能的实现。

首先,写一个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,未加载时显示按钮,加载时就显示进度条。

写一个item.xml,用来定义listview的每个item的视图:

查看源代码     打印     帮助

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

请输入图片描述

本文转载自:http://blog.92coding.com/index.php/archives/288.html

粉丝 5
博文 78
码字总数 10995
作品 0
崇明
私信 提问
Flutter EasyRefresh+ListView+Scoped Model 实现上拉刷新和分页加载

前言: Flutter项目需要实现“上拉刷新和分页加载“的功能,分页可以把大量数据分割成一个个小段,分次加载。这样可以有效避免因为一次load全部数据而导致客户端变慢的问题。在这里我使用Eas...

EmilyWu
07/18
226
0
Android In ListView Loading Data

Android 应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过 分页的形式来展示数据,个人觉得这...

MrLovelyCbb
2012/06/21
167
0
Android中ListView分页加载数据

Android应用开发中,采用ListView组件来展示数据是很常用的功能,当一个应用要展现很多的数据时,一般情况下都不会把所有的数据一次就展示出来,而是通过分页的形式来展示数据,个人觉得这样...

鉴客
2011/11/14
22.4K
0
基于Android官方AsyncListUtil优化经典ListView分页加载机制(二)

基于Android官方AsyncListUtil优化经典ListView分页加载机制(二) 我写的附录文章1,介绍了如何使用Android官方的分页加载框架AsyncListUtil优化改进常见的RecyclerView分页加载实现。Async...

zhangphil
2017/11/27
0
0
Android Room联合AsyncListUtil实现RecyclerView分页加载ORM数据

Android Room联合AsyncListUtil实现RecyclerView分页加载ORM数据 我之前写了一系列关于AsyncListUtil实现RecyclerView和ListView的分页加载机制和技术路线,见附录文章4,5。同时也写了一些列...

zhangphil
2017/11/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

关于运维,该怎么决定它的方向,这个似工作又似兴趣的存在

我之前主要从事网络、桌面、机房管理等相关工作,这些工作使我迷惘,这应该是大多数运维人都经历过的过程; 18年国庆,我从国内前三的消费金融公司裸辞,下海创业,就是想要摆脱这样的困境。...

网络小虾米
29分钟前
5
0
Java Timer的用法

Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { System.out.println("11232"); } }, 200000 , 1000); public void schedule(TimerTask task, long delay......

林词
33分钟前
5
0
使用js动态加载外部js文件以及动态创建script脚本

动态脚本指的是在页面加载时不存在,但将来的某一时刻通过修改该DOM动态添加的脚本。和操作HTML元素一样,创建动态脚本也有两种方式:插入外部文件和直接插入JavaScript代码。 动态加载外的外...

Bing309
40分钟前
3
0
从零开始入门 K8s | Kubernetes 网络概念及策略控制

作者 | 阿里巴巴高级技术专家 叶磊 一、Kubernetes 基本网络模型 本文来介绍一下 Kubernetes 对网络模型的一些想法。大家知道 Kubernetes 对于网络具体实现方案,没有什么限制,也没有给出特...

阿里巴巴云原生
44分钟前
3
0
天气获取

本文转载于:专业的前端网站➨天气获取 $.get("http://wthrcdn.etouch.cn/WeatherApi", { citykey: cityCode }, function (d) { //创建文档对象 var parser = new ......

前端老手
44分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部