<p>上篇博文和大家分享了下拉刷新,这是一个用户体验非常好的操作方式。新浪微薄就是使用这种方式的典型。</p><p>还有个问题,当用户从网络上读取微薄的时候,如果一下子全部加载用户未读的微薄这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容。这时候,我们就需要用到另一个功能,那就是listview的分页了。通过分页分次加载数据,用户看多少就去加载多少。</p><p>通常这也分为两种方式,一种是设置一个按钮,用户点击即加载。另一种是当用户滑动到底部时自动加载。今天我就和大家分享一下这个功能的实现。</p><p>首先,写一个xml文件,moredata.xml,该文件即定义了放在listview底部的视图:</p><pre class="brush:xml;toolbar:false"><?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns: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></pre><p>可以看到是一个按钮和一个进度条。因为只做一个演示,这里简单处理,通过设置控件的visibility,未加载时显示按钮,加载时就显示进度条。</p><p>写一个item.xml,大家应该很熟悉了。用来定义listview的每个item的视图。</p><pre class="brush:xml;toolbar:false">
<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns: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></pre><p>main.xml就不贴了,整个主界面就一个listview。</p><p>直接先看下Activity的代码,在里面实现分页效果。</p><pre class="brush:java;toolbar:false">packagecom.notice.moredate;
importjava.util.ArrayList;
importjava.util.HashMap;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.AbsListView;
importandroid.widget.AbsListView.OnScrollListener;
importandroid.widget.Button;
importandroid.widget.ListView;
importandroid.widget.ProgressBar;
importandroid.widget.SimpleAdapter;
importandroid.widget.Toast;
publicclassMoreDateListActivityextendsActivityimplementsOnScrollListener{
//ListView的Adapter
privateSimpleAdaptermSimpleAdapter;
privateListViewlv;
privateButtonbt;
privateProgressBarpg;
privateArrayList<HashMap<String,String>>list;
//ListView底部View
privateViewmoreView;
privateHandlerhandler;
//设置一个最大的数据条数,超过即不再加载
privateintMaxDateNum;
//最后可见条目的索引
privateintlastVisibleIndex;
/**Calledwhentheactivityisfirstcreated.*/
@Override
publicvoidonCreate(BundlesavedInstanceState){
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=newHandler();
//用map来装载数据,初始化10条数据
list=newArrayList<HashMap<String,String>>();
for(inti=0;i<10;i++){
HashMap<String,String>map=newHashMap<String,String>();
map.put("ItemTitle","第"+i+"行标题");
map.put("ItemText","第"+i+"行内容");
list.add(map);
}
//实例化SimpleAdapter
mSimpleAdapter=newSimpleAdapter(this,list,R.layout.item,
newString[]{"ItemTitle","ItemText"},
newint[]{R.id.tv_title,R.id.tv_content});
//加上底部View,注意要放在setAdapter方法前
lv.addFooterView(moreView);
lv.setAdapter(mSimpleAdapter);
//绑定监听器
lv.setOnScrollListener(this);
bt.setOnClickListener(newOnClickListener(){
@Override
publicvoidonClick(Viewv){
pg.setVisibility(View.VISIBLE);//将进度条可见
bt.setVisibility(View.GONE);//按钮不可见
handler.postDelayed(newRunnable(){
@Override
publicvoidrun(){
loadMoreDate();//加载更多数据
bt.setVisibility(View.VISIBLE);
pg.setVisibility(View.GONE);
mSimpleAdapter.notifyDataSetChanged();//通知listView刷新数据
}
},2000);
}
});
}
privatevoidloadMoreDate(){
intcount=mSimpleAdapter.getCount();
if(count+5<MaxDateNum){
//每次加载5条
for(inti=count;i<count+5;i++){
HashMap<String,String>map=newHashMap<String,String>();
map.put("ItemTitle","新增第"+i+"行标题");
map.put("ItemText","新增第"+i+"行内容");
list.add(map);
}
}else{
//数据已经不足5条
for(inti=count;i<MaxDateNum;i++){
HashMap<String,String>map=newHashMap<String,String>();
map.put("ItemTitle","新增第"+i+"行标题");
map.put("ItemText","新增第"+i+"行内容");
list.add(map);
}
}
}
@Override
publicvoidonScroll(AbsListViewview,intfirstVisibleItem,
intvisibleItemCount,inttotalItemCount){
//计算最后可见条目的索引
lastVisibleIndex=firstVisibleItem+visibleItemCount-1;
//所有的条目已经和最大条数相等,则移除底部的View
if(totalItemCount==MaxDateNum+1){
lv.removeFooterView(moreView);
Toast.makeText(this,"数据全部加载完成,没有更多数据!",Toast.LENGTH_LONG).show();
}
}
@Override
publicvoidonScrollStateChanged(AbsListViewview,intscrollState){
//滑到底部后自动加载,判断listview已经停止滚动并且最后可视的条目等于adapter的条目
if(scrollState==OnScrollListener.SCROLL_STATE_IDLE
&&lastVisibleIndex==mSimpleAdapter.getCount()){
//当滑到底部时自动加载
//pg.setVisibility(View.VISIBLE);
//bt.setVisibility(View.GONE);
//handler.postDelayed(newRunnable(){
//
//@Override
//publicvoidrun(){
//loadMoreDate();
//bt.setVisibility(View.VISIBLE);
//pg.setVisibility(View.GONE);
//mSimpleAdapter.notifyDataSetChanged();
//}
//
//},2000);
}
}
}</pre><p>通过注释,大家应该很容易理解了。这里做下简单的解析。首先要注意的是,addFootView方法一定要在setAdapter方法之前,否则会无效。addFootView方法为listview底部加入一个视图,在本例中就是那个Button加progressbar的视图。当用户点击按钮时,调用loadmoreDate方法,为listview绑定更多的数据,通过adapter的notifyDataSetChanged方法通知listview刷新,显示刚加入的数据。</p><p>这里用handler异步延迟2秒操作,模仿加载过程。同时listview绑定了onScrollListener监听器,并且实现了onScroll和onScrollStateChanged方法。在后者方法中,我们通过判断listview已经停止滚动并且最后可视的条目等于adapter的条目,可以知道用户已经滑动到底部并且自动加载,代码中将这部分代码注释掉了,大家可以自己试下。</p><p>代码中还加入了一个MaxDateNum变量,用来记录最大的数据数量。也就是说网络或者其他地方一共的数据。通过onScroll方法判断用户加载完这些数据后,移除listview底部视图,不让继续加载。同时在loadmoreDate方法中也对最大数据量做相应的操作来判断加载数量。(默认加载5条,不足5条时加载剩余的)。</p><p>看下效果图:</p><p><img src="/up_pic/201812/191007575469.png" title="191007575469.png"/></p><p><img src="/up_pic/201812/191007577595.png" title="191007577595.png"/></p><p><img src="/up_pic/201812/191007579565.png" title="191007579565.png"/></p><p><img src="/up_pic/201812/191007578188.png" title="191007578188.png"/></p><p>就写这么多了,总的来说还是很简单的,但是确实非常有用的一个效果。欢迎留言交流。</p>