当前位置: 移动技术网 > 移动技术>移动开发>Android > Android程序开发之Listview下拉刷新上拉(滑动分页)加载更多

Android程序开发之Listview下拉刷新上拉(滑动分页)加载更多

2019年07月24日  | 移动技术网移动技术  | 我要评论

最近做的类似于微博的项目中,有个android功能要使用到listview的向下拉刷新来刷新最新消息,向上拉刷新(滑动分页)来加载更多。

新浪微博就是使用这种方式的典型。

当用户从网络上读取微博的时候,如果一下子全部加载用户未读的微博这将耗费比较长的时间,造成不好的用户体验,同时一屏的内容也不足以显示如此多的内容。这时候,我们就需要用到另一个功能,那就是listview的分页了,其实这个分页可以做成客户端的分页,也可以做成服务器端的分页(点击加载时,从服务器对应的加载第n页就好了!!!)。通过分页分次加载数据,用户看多少就去加载多少。

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

效果图如下所示:

下拉刷新最主要的流程是:

(1). 下拉,显示提示头部界面(headerview),这个过程提示用户”下拉刷新”

(2). 下拉到一定程度,超出了刷新最基本的下拉界限,我们认为达到了刷新的条件,提示用户可以”松手刷新”了,效果上允许用户继续下拉

(3). 用户松手,可能用户下拉远远不止提示头部界面,所以这一步,先反弹回仅显示提示头部界面,然后提示用户”正在加载”。

(4). 加载完成后,隐藏提示头部界面。

那么让我们看看怎么才能实现呢???

第一步:既然是要显示listview ,那么就应该有个listview 的容器pulldown.xml

<?xml version="1.0" encoding="utf-8"?>
<com.solo.pulldown.pulldownview xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pull_down_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/white">
</com.solo.pulldown.pulldownview> 

第二步:自定义一个listview中显示的item对象pulldown_item.xml

<?xml version="1.0" encoding="utf-8"?>
<textview xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textappearance="?android:attr/textappearancelarge"
android:gravity="center_vertical"
android:paddingleft="6dip"
android:minheight="?android:attr/listpreferreditemheight"
android:textcolor="@android:color/black"
/> 

第三步:定义一个header的xml布局文件pulldown_header.xml

<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingbottom="10dp"
android:paddingtop="10dp" >
<imageview
android:id="@+id/pulldown_header_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignparentleft="true"
android:layout_marginleft="20dp"
android:scaletype="centercrop"
android:src="@drawable/z_arrow_down"
android:visibility="invisible" />
<linearlayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignbottom="@+id/pulldown_header_arrow"
android:layout_aligntop="@+id/pulldown_header_arrow"
android:layout_centerhorizontal="true"
android:gravity="center_vertical"
android:orientation="vertical" >
<textview
android:id="@+id/pulldown_header_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="加载中..." />
<textview
android:id="@+id/pulldown_header_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="更新于:"
android:visibility="gone" />
</linearlayout>
<progressbar
android:id="@+id/pulldown_header_loading"
style="@android:style/widget.progressbar.small.inverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centervertical="true"
android:layout_marginleft="20dp" />
</relativelayout> 

第四步:如果需要向上拉更新更多的话,那就定义一个底部的footer的布局文件,在此为方便起见,只定义一个progressbar跟textview,更加复杂的显示,就交给你们了~~~~~pulldown_footer.xml:

<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingbottom="10dp"
android:paddingtop="10dp" >
<textview
android:id="@+id/pulldown_footer_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerinparent="true"
android:text="更多"
android:textsize="15dp" />
<progressbar
android:id="@+id/pulldown_footer_loading"
style="@android:style/widget.progressbar.small.inverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centervertical="true"
android:layout_marginleft="20dp"
android:visibility="gone" />
</relativelayout> 

第五步:那么主要的文件这才登场:::::::重写listview这个文件主要任务是提供触摸的事件的处理方法。

/**
* <p>一个可以监听listview是否滚动到最顶部或最底部的自定义控件</p>
* 只能监听由触摸产生的,如果是listview本身flying导致的,则不能监听</br>
* 如果加以改进,可以实现监听scroll滚动的具体位置等
*/
public class scrolloverlistview extends listview {
private int mlasty;
private int mtopposition;
private int mbottomposition;
public scrolloverlistview(context context, attributeset attrs, int defstyle) {
super(context, attrs, defstyle);
init();
}
public scrolloverlistview(context context, attributeset attrs) {
super(context, attrs);
init();
}
public scrolloverlistview(context context) {
super(context);
init();
}
private void init(){
mtopposition = 0;
mbottomposition = 0;
}
@override
public boolean ontouchevent(motionevent ev) {
final int action = ev.getaction();
final int y = (int) ev.getrawy();
switch(action){
case motionevent.action_down:{
mlasty = y;
final boolean ishandled = monscrolloverlistener.onmotiondown(ev);
if (ishandled) {
mlasty = y;
return ishandled;
}
break;
}
case motionevent.action_move:{
final int childcount = getchildcount();
if(childcount == 0) return super.ontouchevent(ev);
final int itemcount = getadapter().getcount() - mbottomposition;
final int deltay = y - mlasty;
//dlog.d("lasty=%d y=%d", mlasty, y);
final int firsttop = getchildat(0).gettop();
final int listpadding = getlistpaddingtop();
final int lastbottom = getchildat(childcount - 1).getbottom();
final int end = getheight() - getpaddingbottom();
final int firstvisibleposition = getfirstvisibleposition();
final boolean ishandlemotionmove = monscrolloverlistener.onmotionmove(ev, deltay);
if(ishandlemotionmove){
mlasty = y;
return true;
}
//dlog.d("firstvisibleposition=%d firsttop=%d listpaddingtop=%d deltay=%d", firstvisibleposition, firsttop, listpadding, deltay);
if (firstvisibleposition <= mtopposition && firsttop >= listpadding && deltay > 0) {
final boolean ishandleonlistviewtopandpulldown;
ishandleonlistviewtopandpulldown = monscrolloverlistener.onlistviewtopandpulldown(deltay);
if(ishandleonlistviewtopandpulldown){
mlasty = y;
return true;
}
}
// dlog.d("lastbottom=%d end=%d deltay=%d", lastbottom, end, deltay);
if (firstvisibleposition + childcount >= itemcount && lastbottom <= end && deltay < 0) {
final boolean ishandleonlistviewbottomandpulldown;
ishandleonlistviewbottomandpulldown = monscrolloverlistener.onlistviewbottomandpullup(deltay);
if(ishandleonlistviewbottomandpulldown){
mlasty = y;
return true;
}
}
break;
}
case motionevent.action_up:{
final boolean ishandlermotionup = monscrolloverlistener.onmotionup(ev);
if (ishandlermotionup) {
mlasty = y;
return true;
}
break;
}
}
mlasty = y;
return super.ontouchevent(ev);
}
/**空的*/
private onscrolloverlistener monscrolloverlistener = new onscrolloverlistener(){
@override
public boolean onlistviewtopandpulldown(int delta) {
return false;
}
@override
public boolean onlistviewbottomandpullup(int delta) {
return false;
}
@override
public boolean onmotiondown(motionevent ev) {
return false;
}
@override
public boolean onmotionmove(motionevent ev, int delta) {
return false;
}
@override
public boolean onmotionup(motionevent ev) {
return false;
}
};
// =============================== public method ===============================
/**
* 可以自定义其中一个条目为头部,头部触发的事件将以这个为准,默认为第一个
*
* @param index 正数第几个,必须在条目数范围之内
*/
public void settopposition(int index){
if(getadapter() == null)
throw new nullpointerexception("you must set adapter before settopposition!");
if(index < 0)
throw new illegalargumentexception("top position must > 0");
mtopposition = index;
}
/**
* 可以自定义其中一个条目为尾部,尾部触发的事件将以这个为准,默认为最后一个
*
* @param index 倒数第几个,必须在条目数范围之内
*/
public void setbottomposition(int index){
if(getadapter() == null)
throw new nullpointerexception("you must set adapter before setbottonposition!");
if(index < 0)
throw new illegalargumentexception("bottom position must > 0");
mbottomposition = index;
}
/**
* 设置这个listener可以监听是否到达顶端,或者是否到达低端等事件</br>
*
* @see onscrolloverlistener
*/
public void setonscrolloverlistener(onscrolloverlistener onscrolloverlistener){
monscrolloverlistener = onscrolloverlistener;
}
/**
* 滚动监听接口</br>
* @see scrolloverlistview#setonscrolloverlistener(onscrolloverlistener)
*
*/
public interface onscrolloverlistener {
/**
* 到达最顶部触发
*
* @param delta 手指点击移动产生的偏移量
* @return
*/
boolean onlistviewtopandpulldown(int delta);
/**
* 到达最底部触发
*
* @param delta 手指点击移动产生的偏移量
* @return
*/
boolean onlistviewbottomandpullup(int delta);
/**
* 手指触摸按下触发,相当于{@link motionevent#action_down}
*
* @return 返回true表示自己处理
* @see view#ontouchevent(motionevent)
*/
boolean onmotiondown(motionevent ev);
/**
* 手指触摸移动触发,相当于{@link motionevent#action_move}
*
* @return 返回true表示自己处理
* @see view#ontouchevent(motionevent)
*/
boolean onmotionmove(motionevent ev, int delta);
/**
* 手指触摸后提起触发,相当于{@link motionevent#action_up}
*
* @return 返回true表示自己处理
* @see view#ontouchevent(motionevent)
*/
boolean onmotionup(motionevent ev);
}
} 

第六步:下拉刷新控件,真正实现下拉刷新的是这个控件,而上面的那个scrolloverlistview只是提供触摸的事件等

/**
* 下拉刷新控件</br>
* 真正实现下拉刷新的是这个控件,
* scrolloverlistview只是提供触摸的事件等
*/
public class pulldownview extends linearlayout implements onscrolloverlistener{
private static final string tag = "pulldownview";
private static final int start_pull_deviation = 50; // 移动误差
private static final int auto_incremental = 10; // 自增量,用于回弹
private static final int what_did_load_data = 1; // handler what 数据加载完毕
private static final int what_on_refresh = 2; // handler what 刷新中
private static final int what_did_refresh = 3; // handler what 已经刷新完
private static final int what_set_header_height = 4;// handler what 设置高度
private static final int what_did_more = 5; // handler what 已经获取完更多
private static final int default_header_view_height = 105; // 头部文件原本的高度
private static simpledateformat dateformat = new simpledateformat("mm-dd hh:mm");
private view mheaderview;
private layoutparams mheaderviewparams;
private textview mheaderviewdateview;
private textview mheadertextview;
private imageview mheaderarrowview;
private view mheaderloadingview;
private view mfooterview;
private textview mfootertextview;
private view mfooterloadingview;
private scrolloverlistview mlistview;
private onpulldownlistener monpulldownlistener;
private rotateanimation mrotateoto180animation;
private rotateanimation mrotate180to0animation;
private int mheaderincremental; // 增量
private float mmotiondownlasty; // 按下时候的y轴坐标
private boolean misdown; // 是否按下
private boolean misrefreshing; // 是否下拉刷新中
private boolean misfetchmoreing; // 是否获取更多中
private boolean mispullupdone; // 是否回推完成
private boolean menableautofetchmore; // 是否允许自动获取更多
// 头部文件的状态
private static final int header_view_state_idle = 0; // 空闲
private static final int header_view_state_not_over_height = 1; // 没有超过默认高度
private static final int header_view_state_over_height = 2; // 超过默认高度
private int mheaderviewstate = header_view_state_idle;
public pulldownview(context context, attributeset attrs) {
super(context, attrs);
initheaderviewandfooterviewandlistview(context);
}
public pulldownview(context context) {
super(context);
initheaderviewandfooterviewandlistview(context);
}
/*
* ==================================
* public method
* 外部使用,具体就是用这几个就可以了
*
* ==================================
*/
/**
* 刷新事件接口
*/
public interface onpulldownlistener {
void onrefresh();
void onmore();
}
/**
* 通知加载完了数据,要放在adapter.notifydatasetchanged后面
* 当你加载完数据的时候,调用这个notifydidload()
* 才会隐藏头部,并初始化数据等
*/
public void notifydidload() {
muihandler.sendemptymessage(what_did_load_data);
}
/**
* 通知已经刷新完了,要放在adapter.notifydatasetchanged后面
* 当你执行完刷新任务之后,调用这个notifydidrefresh()
* 才会隐藏掉头部文件等操作
*/
public void notifydidrefresh() {
muihandler.sendemptymessage(what_did_refresh);
}
/**
* 通知已经获取完更多了,要放在adapter.notifydatasetchanged后面
* 当你执行完更多任务之后,调用这个notyfydidmore()
* 才会隐藏加载圈等操作
*/
public void notifydidmore() {
muihandler.sendemptymessage(what_did_more);
}
/**
* 设置监听器
* @param listener
*/
public void setonpulldownlistener(onpulldownlistener listener){
monpulldownlistener = listener;
}
/**
* 获取内嵌的listview
* @return scrolloverlistview
*/
public listview getlistview(){
return mlistview;
}
/**
* 是否开启自动获取更多
* 自动获取更多,将会隐藏footer,并在到达底部的时候自动刷新
* @param index 倒数第几个触发
*/
public void enableautofetchmore(boolean enable, int index){
if(enable){
mlistview.setbottomposition(index);
mfooterloadingview.setvisibility(view.visible);
}else{
mfootertextview.settext("更多");
mfooterloadingview.setvisibility(view.gone);
}
menableautofetchmore = enable;
}
/*
* ==================================
* private method
* 具体实现下拉刷新等操作
*
* ==================================
*/
/**
* 初始化界面
*/
private void initheaderviewandfooterviewandlistview(context context){
setorientation(linearlayout.vertical);
//setdrawingcacheenabled(false);
/*
* 自定义头部文件
* 放在这里是因为考虑到很多界面都需要使用
* 如果要修改,和它相关的设置都要更改
*/
mheaderview = layoutinflater.from(context).inflate(r.layout.pulldown_header, null);
mheaderviewparams = new layoutparams(layoutparams.fill_parent, layoutparams.wrap_content);
addview(mheaderview, 0, mheaderviewparams);
mheadertextview = (textview) mheaderview.findviewbyid(r.id.pulldown_header_text);
mheaderarrowview = (imageview) mheaderview.findviewbyid(r.id.pulldown_header_arrow);
mheaderloadingview = mheaderview.findviewbyid(r.id.pulldown_header_loading);
// 注意,图片旋转之后,再执行旋转,坐标会重新开始计算
mrotateoto180animation = new rotateanimation(0, 180,
animation.relative_to_self, 0.5f,
animation.relative_to_self, 0.5f);
mrotateoto180animation.setduration(250);
mrotateoto180animation.setfillafter(true);
mrotate180to0animation = new rotateanimation(180, 0,
animation.relative_to_self, 0.5f,
animation.relative_to_self, 0.5f);
mrotate180to0animation.setduration(250);
mrotate180to0animation.setfillafter(true);
/**
* 自定义脚部文件
*/
mfooterview = layoutinflater.from(context).inflate(r.layout.pulldown_footer, null);
mfootertextview = (textview) mfooterview.findviewbyid(r.id.pulldown_footer_text);
mfooterloadingview = mfooterview.findviewbyid(r.id.pulldown_footer_loading);
mfooterview.setonclicklistener(new onclicklistener() {
@override
public void onclick(view v) {
if(!misfetchmoreing){
misfetchmoreing = true;
mfooterloadingview.setvisibility(view.visible);
monpulldownlistener.onmore();
}
}
});
/*
* scrolloverlistview 同样是考虑到都是使用,所以放在这里
* 同时因为,需要它的监听事件
*/
mlistview = new scrolloverlistview(context);
mlistview.setonscrolloverlistener(this);
mlistview.setcachecolorhint(0);
addview(mlistview, layoutparams.fill_parent, layoutparams.fill_parent);
// 空的listener
monpulldownlistener = new onpulldownlistener() {
@override
public void onrefresh() {}
@override
public void onmore() {}
};
}
/**
* 在下拉和回推的时候检查头部文件的状态</br>
* 如果超过了默认高度,就显示松开可以刷新,
* 否则显示下拉可以刷新
*/
private void checkheaderviewstate(){
if(mheaderviewparams.height >= default_header_view_height){
if(mheaderviewstate == header_view_state_over_height) return;
mheaderviewstate = header_view_state_over_height;
mheadertextview.settext("松开可以刷新");
mheaderarrowview.startanimation(mrotateoto180animation);
}else{
if(mheaderviewstate == header_view_state_not_over_height
|| mheaderviewstate == header_view_state_idle) return;
mheaderviewstate = header_view_state_not_over_height;
mheadertextview.settext("下拉可以刷新");
mheaderarrowview.startanimation(mrotate180to0animation);
}
}
private void setheaderheight(final int height){
mheaderincremental = height;
mheaderviewparams.height = height;
mheaderview.setlayoutparams(mheaderviewparams);
}
/**
* 自动隐藏动画
*/
class hideheaderviewtask extends timertask{
@override
public void run() {
if(misdown) {
cancel();
return;
}
mheaderincremental -= auto_incremental;
if(mheaderincremental > 0){
muihandler.sendemptymessage(what_set_header_height);
}else{
mheaderincremental = 0;
muihandler.sendemptymessage(what_set_header_height);
cancel();
}
}
}
/**
* 自动显示动画
*/
class showheaderviewtask extends timertask{
@override
public void run() {
if(misdown) {
cancel();
return;
}
mheaderincremental -= auto_incremental;
if(mheaderincremental > default_header_view_height){
muihandler.sendemptymessage(what_set_header_height);
}else{
mheaderincremental = default_header_view_height;
muihandler.sendemptymessage(what_set_header_height);
if(!misrefreshing){
misrefreshing = true;
muihandler.sendemptymessage(what_on_refresh);
}
cancel();
}
}
}
private handler muihandler = new handler(){
@override
public void handlemessage(message msg) {
switch (msg.what) {
case what_did_load_data:{
mheaderviewparams.height = 0;
mheaderloadingview.setvisibility(view.gone);
mheadertextview.settext("下拉可以刷新");
mheaderviewdateview = (textview) mheaderview.findviewbyid(r.id.pulldown_header_date);
mheaderviewdateview.setvisibility(view.visible);
mheaderviewdateview.settext("更新于:" + dateformat.format(new date(system.currenttimemillis())));
mheaderarrowview.setvisibility(view.visible);
showfooterview();
return;
}
case what_on_refresh:{
// 要清除掉动画,否则无法隐藏
mheaderarrowview.clearanimation();
mheaderarrowview.setvisibility(view.invisible);
mheaderloadingview.setvisibility(view.visible);
monpulldownlistener.onrefresh();
return;
}
case what_did_refresh :{
misrefreshing = false;
mheaderviewstate = header_view_state_idle;
mheaderarrowview.setvisibility(view.visible);
mheaderloadingview.setvisibility(view.gone);
mheaderviewdateview.settext("更新于:" + dateformat.format(new date(system.currenttimemillis())));
setheaderheight(0);
showfooterview();
return;
}
case what_set_header_height :{
setheaderheight(mheaderincremental);
return;
}
case what_did_more :{
misfetchmoreing = false;
mfootertextview.settext("更多");
mfooterloadingview.setvisibility(view.gone);
}
}
}
};
/**
* 显示脚步脚部文件
*/
private void showfooterview(){
if(mlistview.getfooterviewscount() == 0 && isfillscreenitem()){
mlistview.addfooterview(mfooterview);
mlistview.setadapter(mlistview.getadapter());
}
}
/**
* 条目是否填满整个屏幕
*/
private boolean isfillscreenitem(){
final int firstvisibleposition = mlistview.getfirstvisibleposition();
final int lastvisiblepostion = mlistview.getlastvisibleposition() - mlistview.getfooterviewscount();
final int visibleitemcount = lastvisiblepostion - firstvisibleposition + 1;
final int totalitemcount = mlistview.getcount() - mlistview.getfooterviewscount();
if(visibleitemcount < totalitemcount) return true;
return false;
}
/*
* ==================================
* 实现 onscrolloverlistener接口
*
*
* ==================================
*/
@override
public boolean onlistviewtopandpulldown(int delta) {
if(misrefreshing || mlistview.getcount() - mlistview.getfooterviewscount() == 0) return false;
int absdelta = math.abs(delta);
final int i = (int) math.ceil((double)absdelta / 2);
mheaderincremental += i;
if(mheaderincremental >= 0){ // && mincremental <= mmaxheight
setheaderheight(mheaderincremental);
checkheaderviewstate();
}
return true;
}
@override
public boolean onlistviewbottomandpullup(int delta) {
if(!menableautofetchmore || misfetchmoreing) return false;
// 数量充满屏幕才触发
if(isfillscreenitem()){
misfetchmoreing = true;
mfootertextview.settext("加载更多中...");
mfooterloadingview.setvisibility(view.visible);
monpulldownlistener.onmore();
return true;
}
return false;
}
@override
public boolean onmotiondown(motionevent ev) {
misdown = true;
mispullupdone = false;
mmotiondownlasty = ev.getrawy();
return false;
}
@override
public boolean onmotionmove(motionevent ev, int delta) {
//当头部文件回推消失的时候,不允许滚动
if(mispullupdone) return true;
// 如果开始按下到滑动距离不超过误差值,则不滑动
final int absmotiony = (int) math.abs(ev.getrawy() - mmotiondownlasty);
if(absmotiony < start_pull_deviation) return true;
final int absdelta = math.abs(delta);
final int i = (int) math.ceil((double)absdelta / 2);
// ontopdown在顶部,并上回推和ontopup相对
if(mheaderviewparams.height > 0 && delta < 0){
mheaderincremental -= i;
if(mheaderincremental > 0){
setheaderheight(mheaderincremental);
checkheaderviewstate();
}else{
mheaderviewstate = header_view_state_idle;
mheaderincremental = 0;
setheaderheight(mheaderincremental);
mispullupdone = true;
}
return true;
}
return false;
}
@override
public boolean onmotionup(motionevent ev) {
misdown = false;
// 避免和点击事件冲突
if(mheaderviewparams.height > 0){
// 判断头文件拉动的距离与设定的高度,小了就隐藏,多了就固定高度
int x = mheaderincremental - default_header_view_height;
timer timer = new timer(true);
if(x < 0){
timer.scheduleatfixedrate(new hideheaderviewtask(), 0, 10);
}else{
timer.scheduleatfixedrate(new showheaderviewtask(), 0, 10);
}
return true;
}
return false;
}
}

第七步:这个java文件就是封装数据,然后调用上两个文件就好了。废话不多说,上代码:::::

public class pulldownactivity extends activity implements onpulldownlistener, onitemclicklistener{
private static final int what_did_load_data = 0;
private static final int what_did_refresh = 1;
private static final int what_did_more = 2;
private listview mlistview;
private arrayadapter<string> madapter;
private pulldownview mpulldownview;
private list<string> mstrings = new arraylist<string>();
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.pulldown);
/*
* 1.使用pulldownview
* 2.设置onpulldownlistener
* 3.从mpulldownview里面获取listview
*/
mpulldownview = (pulldownview) findviewbyid(r.id.pull_down_view);
mpulldownview.setonpulldownlistener(this);
mlistview = mpulldownview.getlistview();
mlistview.setonitemclicklistener(this);
madapter = new arrayadapter<string>(this, r.layout.pulldown_item, mstrings);
mlistview.setadapter(madapter);
mpulldownview.enableautofetchmore(true, 1);
loaddata();
}
private void loaddata(){
new thread(new runnable() {
@override
public void run() {
try {
thread.sleep(2000);
} catch (interruptedexception e) {
e.printstacktrace();
}
list<string> strings = new arraylist<string>();
for (string body : mstringarray) {
strings.add(body);
}
message msg = muihandler.obtainmessage(what_did_load_data);
msg.obj = strings;
msg.sendtotarget();
}
}).start();
}
@override
public void onrefresh() {
new thread(new runnable() {
@override
public void run() {
try {
thread.sleep(2000);
} catch (interruptedexception e) {
e.printstacktrace();
}
message msg = muihandler.obtainmessage(what_did_refresh);
msg.obj = "after refresh " + system.currenttimemillis();
msg.sendtotarget();
}
}).start();
}
@override
public void onmore() {
new thread(new runnable() {
@override
public void run() {
try {
thread.sleep(2000);
} catch (interruptedexception e) {
e.printstacktrace();
}
message msg = muihandler.obtainmessage(what_did_more);
msg.obj = "after more " + system.currenttimemillis();
msg.sendtotarget();
}
}).start();
}
private handler muihandler = new handler(){
@override
public void handlemessage(message msg) {
switch (msg.what) {
case what_did_load_data:{
if(msg.obj != null){
list<string> strings = (list<string>) msg.obj;
if(!strings.isempty()){
mstrings.addall(strings);
madapter.notifydatasetchanged();
}
}
// 诉它数据加载完毕;
mpulldownview.notifydidload();
break;
}
case what_did_refresh :{
string body = (string) msg.obj;
mstrings.add(0, body);
madapter.notifydatasetchanged();
// 告诉它更新完毕
mpulldownview.notifydidrefresh();
break;
}
case what_did_more:{
string body = (string) msg.obj;
mstrings.add(body);
madapter.notifydatasetchanged();
// 告诉它获取更多完毕
mpulldownview.notifydidmore();
break;
}
}
}
};
@override
public void onitemclick(adapterview<?> parent, view view, int position, long id) {
toast.maketext(this, "啊,你点中我了 " + position, toast.length_short).show();
}
// 模拟数据
private string[] mstringarray = {
"abbaye de belloc", "abbaye du mont des cats", "abertam", "abondance", "ackawi",
"acorn", "adelost", "affidelice au chablis", "afuega'l pitu", "airag", "airedale",
"aisy cendre", "allgauer emmentaler", "alverca", "ambert", "american cheese"
};
} 

整个程序就这么完成了,总之,可以使用前两个封装好的文件,然后,调用就好了~~~~没什么太难的地方。

以上所述是小编给大家介绍的android程序开发之listview下拉刷新上拉(滑动分页)加载更多,希望对大家有所帮助

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网