android上拉加载+下拉刷新

根据imooc慕课网有关上拉加载和下拉刷新的相关视频学习后个人修改(不实现onscroll接口)+整理,限于本人水平,该view无法做到完全封装,使用该view需要重写lmxlistview中的getReloadDataForlmxListviewh和getRefreshDataForlmxListview并手动调用removeFooterView(footerView)和refreshComplete();

demo实现上拉/下拉时进行网络请求(打出到log中,没有更改lmxlistview),并在请求完成后去除header和footer,这里使用的是我的网络请求封装类lmxhttpclient,可另行下载

使用lmxlistview需要加入我的布局文件header和footer,建议大家自己去慕课网上学习下,感觉这次的内容综合性比较高

错误之处望大神们包涵指正,项目源码-->

http://download.csdn.net/detail/u014727233/9510889



lmxlistview的实现:



/*
 * getReloadDataForlmxListview--->实现上拉加载具体业务,业务完成后,需要在主线程调用removeFooterView(footerView)
 * getRefreshDataForlmxListview--->实现下拉刷新具体业务,业务完成后,需要在主线程调用refreshComplete();
 * 需要拷贝相关图片资源、header.xml、footer.xml
 */
package com.lmx.views;


import java.util.HashMap;


import com.example.lmxlib.R;
import com.example.lmxlib.RefreshableReloadableListview;
import com.lmx.tools.lmxHttpClient;


import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;


public class lmxListview extends ListView {


/***********************/
lmxHttpClient client;
/***********************/
public Context context;
public LayoutInflater inflater;
public View headerView, footerView;
public int headerHeight;
public int totalCount = 0;
public TextView tv;
public boolean canRefresh = false;
public boolean canLoad = false;
// 允许下拉刷新时,手指按下时的Y坐标
public int startY;
public int endY;
public int deltaY;
int firstVisibleItemId;
public ProgressBar pb;
public ImageView img_arr;
public boolean needCheck = true;
public int STATE_READY = 1; // 准备就绪状态,此时释放手指可以刷新
public int STATE_UNREADY = 0; // 未就绪状态
public int state = STATE_UNREADY; // 默认状态为未就绪
RotateAnimation anim;
public final int DERICTION_DOWN = 0;
public final int DERICTION_UP = 1;
public int arr_direction = DERICTION_DOWN;
public boolean pullUpEnabled = false;


public lmxListview(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
this.context = context;
init();
}


public lmxListview(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
this.context = context;
init();
}


public lmxListview(Context context) {
super(context);
// TODO Auto-generated constructor stub
this.context = context;
init();
}


public void init() {
inflater = LayoutInflater.from(context);
headerView = inflate(context, R.layout.header, null);
footerView = inflater.inflate(R.layout.footer, null);
tv = (TextView) headerView.findViewById(R.id.tv_pullup);
img_arr = (ImageView) headerView.findViewById(R.id.img_pullup);
pb = (ProgressBar) headerView.findViewById(R.id.pb);
/**** 测量头部高度 ****/
measureView(headerView);
headerHeight = headerView.getMeasuredHeight();
/**** 定义箭头动画 ****/
anim = new RotateAnimation(0, 540, RotateAnimation.RELATIVE_TO_SELF,
0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(500);
anim.setFillAfter(true);
Log.i("res", "测量到头部的高度:" + headerHeight);
this.addHeaderView(headerView);
setTopPadding(headerHeight);
firstVisibleItemId = this.getFirstVisiblePosition();
// 如果当前屏幕中有第一项,允许下拉刷新事件触发
if (firstVisibleItemId == 0) {
canRefresh = true;
}
}


public void setTopPadding(int topPadding) {
Log.i("res", "setTopPadding执行,toppadding-->" + topPadding);
this.setPadding(headerView.getPaddingLeft(), -topPadding,
headerView.getPaddingRight(), headerView.getPaddingBottom());
headerView.invalidate();
}


public void measureView(View view) {
ViewGroup.LayoutParams params = view.getLayoutParams();
if (params == null) {
params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
}
int width = ViewGroup.getChildMeasureSpec(0, 0, params.width);
int height;
int tempHeight = params.height;
if (tempHeight > 0) {
height = MeasureSpec.makeMeasureSpec(tempHeight,
MeasureSpec.EXACTLY);
} else {
height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
view.measure(width, height);
}


@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub


switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
if (this.getFirstVisiblePosition() == 0) {
canRefresh = true;
} else {
canRefresh = false;
}
if (pullUpEnabled) {
Log.i("res", "MotionEvent.ACTION_DOWN执行,totalCount - 1--->"
+ (totalCount - 1));
if (this.getLastVisiblePosition() == (totalCount - 1)) {
canLoad = true;
} else {
canLoad = false;
}
}
Log.i("res", "MotionEvent.ACTION_DOWN将canRefresh修改为" + canRefresh);
startY = (int) ev.getY();
break;


case MotionEvent.ACTION_MOVE:
if (needCheck) {
if (canRefresh == true) {
endY = (int) ev.getY();
Log.i("res", "MotionEvent.ACTION_MOVE检测中,endY:" + endY);
deltaY = endY - startY;
if (deltaY > 0 && deltaY < headerHeight) {
this.setTopPadding(-deltaY / 2);
if (state == STATE_READY) {
// 手指移动距离不够 不能触发刷新
state = STATE_UNREADY;
}
} else if (deltaY > headerHeight && state != STATE_READY) {
this.setTop(0);
tv.setText("释放立即刷新!");
state = STATE_READY;
// 手指移动位置超过header高度,此时箭头展示旋转动画
img_arr.startAnimation(anim);
}
}
}
break;


case MotionEvent.ACTION_UP:
if (deltaY > headerHeight) {
needCheck = false;
Log.i("res", "进入正在刷新状态...");
refreshing();
}
if (canLoad == true && pullUpEnabled) {
Log.i("res", "MotionEvent.ACTION_UP执行,canLoad=" + canLoad);
endY = (int) ev.getY();
deltaY = startY - endY;
if (deltaY > headerHeight * 1.5) {
this.addFooterView(footerView);
Log.i("res", "进入加载状态,添加底部加载布局");
// 使用lmxListview需要重写加载更多业务
getReloadDataForlmxListview();
}
}
startY = 0;
endY = 0;
break;


default:
break;
}


return super.onTouchEvent(ev);
}


public void refreshing() {
tv.setText("正在刷新...");
img_arr.clearAnimation();
img_arr.setVisibility(View.GONE);
pb.setVisibility(View.VISIBLE);
// 重写上拉刷新业务 getRefreshDataForlmxListview
getRefreshDataForlmxListview();
}


public void refreshComplete() {
Log.i("res", "进入refreshComplete");
pb.setVisibility(View.GONE);
tv.setText("刷新成功!");
this.setTopPadding(headerHeight);
tv.setText("下拉可以刷新!");
img_arr.setVisibility(View.VISIBLE);
img_arr.clearAnimation();
needCheck = true;
}


// 设置listview可以上拉加载 需要对listview设置完adapter后调用,重新获取llistview中的数据个数
public void setPullUpReloadEnabled(boolean b) {
if (b) {
totalCount = this.getCount();
pullUpEnabled = true;
} else {
pullUpEnabled = false;
}
}


/**
* 下拉刷新具体业务

* @Title: getRefreshDataForlmxListview
* @Description: TODO(下拉刷新具体业务)
* @param 参数说明
* @return void 返回类型
* @throws
*/
public void getRefreshDataForlmxListview() {


// 这里执行上下拉刷新的对应业务,业务完成后,需要在主线程调用refreshComplete();
// 如下


final String url = "http://ground.kxfresh.com:8188/api/trade/storeTradeDetailList";
final int timeout = 5000;
HashMap<String, String> map = new HashMap<String, String>();
map.put("channelId", "1");
map.put("storeId", "0");
map.put("status", "1");
map.put("page", "1");
map.put("pageSize", "6");
client = new lmxHttpClient(url, timeout, map) {


@Override
public void onRequestSuccess(String json) {
// TODO Auto-generated method stub
Log.i("res", "请求成功,返回json:" + json);
RefreshableReloadableListview.mactivity
.runOnUiThread(new Runnable() {
public void run() {
refreshComplete();
}
});
}


@Override
public void onRequestFailure() {
// TODO Auto-generated method stub
Log.i("res", "请求失败,返回json:");
RefreshableReloadableListview.mactivity
.runOnUiThread(new Runnable() {
public void run() {
refreshComplete();
}
});
}
};
client.doGet();
}


/**
* 上拉加载具体业务

* @Title: getReloadDataForlmxListview
* @Description: TODO(上拉加载具体业务)
* @param 参数说明
* @return void 返回类型
* @throws
*/
public void getReloadDataForlmxListview() {


// 这里执行上拉加载的对应业务,业务完成后,需要在主线程调用removeFooterView(footerView);
// 如下
final String url = "http://ground.kxfresh.com:8188/api/trade/storeTradeDetailList";
final int timeout = 5000;
HashMap<String, String> map = new HashMap<String, String>();
map.put("channelId", "1");
map.put("storeId", "0");
map.put("status", "1");
map.put("page", "1");
map.put("pageSize", "6");
client = new lmxHttpClient(url, timeout, map) {


@Override
public void onRequestSuccess(String json) {
// TODO Auto-generated method stub
Log.i("res", "请求成功,返回json:" + json);
RefreshableReloadableListview.mactivity
.runOnUiThread(new Runnable() {
public void run() {
removeFooterView(footerView);
}
});
}


@Override
public void onRequestFailure() {
// TODO Auto-generated method stub
Log.i("res", "请求失败,返回json:");
RefreshableReloadableListview.mactivity
.runOnUiThread(new Runnable() {
public void run() {
removeFooterView(footerView);
}
});
}
};
client.doGet();
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值