<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">先上一张效果图</span>
关于下拉刷新的ListView网上有许多开源的项目pulltorefresh
下面简单介绍一下原理
下拉刷新的界面是放在listview的headerveiw中的通过改变headerview的toppadding从而达到headerview的隐藏与现实移动效果
listview有四种状态
正常状态
下拉刷新 (当手势移动距离小于某个值时一直处于该状态)
松开刷新 (当手势移动距离大于特定值时变成该状态)
正在刷新 (释放是状态为松开刷新状态)
package com.example.reflishlistview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
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.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
public class ReflishView extends ListView implements OnScrollListener {
private enum State {
NOMAL, PULL, RELSE, REFALSH
}
private int fistitem; //第一个显示的索引
private State state = State.NOMAL;
private View header;
private LinearLayout.LayoutParams paras;
private int headerheight;
private LinearLayout headerview;
private FrameLayout flyimg;
private ImageView img_del;
private ImageView img_loading;
private AnimationDrawable animation;
public ReflishView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ReflishView(Context context) {
this(context, null);
}
public ReflishView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
header = LayoutInflater.from(context).inflate(R.layout.header, null);
img_loading=(ImageView) header.findViewById(R.id.loading);
img_loading.setBackgroundResource(R.drawable.loading);
animation=(AnimationDrawable)img_loading.getBackground();
img_del = (ImageView) header.findViewById(R.id.del);
img_del.setOnClickListener(l);
tv_sm = (TextView) header.findViewById(R.id.tv_sm);
sj = (TextView) header.findViewById(R.id.sj);
this.addHeaderView(header);
headerview = (LinearLayout) header.findViewById(R.id.lly);
flyimg = (FrameLayout) header.findViewById(R.id.framelayout);
measureView(headerview);
headerheight = headerview.getMeasuredHeight();
Log.v("tag", headerheight + "");
settopPadding(0);
this.setOnScrollListener(this);
}
private OnClickListener l = new OnClickListener() {
@Override
public void onClick(View arg0) {
flyimg.removeAllViews();
}
};
@SuppressLint("NewApi")
private void settopPadding(int top) {
headerview.setPadding(headerview.getPaddingLeft(), -headerheight + top,
headerview.getPaddingRight(), headerview.getPaddingEnd());
headerview.invalidate();
}
// 计算站的空间
private void measureView(View view) {
ViewGroup.LayoutParams p = view.getLayoutParams();
if (p == null) {
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
int width = ViewGroup.getChildMeasureSpec(0, 0, p.width);
int height;
int tempHeight = p.height;
if (tempHeight > 0) {
height = MeasureSpec.makeMeasureSpec(tempHeight,
MeasureSpec.EXACTLY);
} else {
height = MeasureSpec.makeMeasureSpec(tempHeight,
MeasureSpec.UNSPECIFIED);
}
view.measure(width, height);
}
private int downy;// 记录点击时的y坐标
private TextView tv_sm;
private TextView sj;
private void UpdateView() {
switch (state) {
case NOMAL:
animation.stop();
tv_sm.setText("下拉刷新");
settopPadding(0);
break;
case PULL:
animation.stop();
tv_sm.setText("下拉刷新");
break;
case RELSE:
animation.stop();
tv_sm.setText("松开刷新");
break;
case REFALSH:
animation.stop();
animation.start();
tv_sm.setText("正在刷新");
if(onrefreshlistener!=null)
{
onrefreshlistener.onRefresh();
}
break;
}
}
public void RefreshComplete()
{
state=State.NOMAL;
sj.setText( new java.util.Date().toLocaleString());
UpdateView();
}
public interface OnRefreshListener
{
void onRefresh();
}
private OnRefreshListener onrefreshlistener;
public void setOnrefreshlistener(OnRefreshListener onrefreshlistener) {
this.onrefreshlistener = onrefreshlistener;
}
/****
* 移动处理
*
* @param ev
*/
private void onMove(MotionEvent ev) {
int tempy = (int) ev.getY();
int space = tempy - downy;
switch (state) {
case NOMAL:
UpdateView();
if (space > 0 && fistitem == 0) {
state = State.PULL;
}
break;
case PULL:
UpdateView();
if (space > headerheight + 50) {
state = State.RELSE;
} else {
settopPadding(space);
}
break;
case RELSE:
UpdateView();
break;
case REFALSH:
//UpdateView();
break;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (state == State.NOMAL && fistitem == 0) {
downy = (int) ev.getY(); // 记录点击下的坐标
state = State.PULL;
}
break;
case MotionEvent.ACTION_MOVE:
onMove(ev);
break;
case MotionEvent.ACTION_UP:
if(state==State.PULL&&fistitem==0)
{
settopPadding(0);
state=State.NOMAL;
UpdateView();
}
if(state==State.RELSE&&fistitem==0)
{
settopPadding(headerheight);
state=State.REFALSH;
UpdateView();
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
@Override
public void onScroll(AbsListView arg0, int firstvisibleitem,
int visibleitemcount, int totalitmcount) {
fistitem = firstvisibleitem;
Log.v("tag", "firstvisibleitem" + firstvisibleitem + "");
}
}
关于listview的使用 大家都知道关于android UI的更新必须放在主线程中的
所以当我们在activity的子线程获取完数据后一定要通知 listview 改变它的状态从而更新ui 这里简单用一下 handler Thread 演示一下 当然也可以用 asyncTask
下面是activity 使用代码
package com.example.reflishlistview;
import java.util.ArrayList;
import java.util.List;
import com.example.reflishlistview.ReflishView.OnRefreshListener;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
public class MainActivity extends Activity implements OnRefreshListener {
private ReflishView listview;
private List<String> data;
private MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InitView();
initData();
}
private void initData()
{
data=new ArrayList<String>();
for(int i=0;i<100;i++)
data.add(i+"");
adapter=new MyAdapter();
listview.setAdapter(adapter);
}
private void InitView()
{
listview=(ReflishView)this.findViewById(R.id.listView);
listview.setOnrefreshlistener(this);
}
class MyAdapter extends BaseAdapter
{
@Override
public int getCount() {
return data!=null?data.size():0;
}
@Override
public Object getItem(int arg0) {
return arg0;
}
@Override
public long getItemId(int arg0) {
return 0;
}
@Override
public View getView(int arg0, View contentview, ViewGroup arg2) {
if(contentview==null)
{
contentview=LayoutInflater.from(MainActivity.this).inflate(R.layout.item, null);
}
return contentview;
}
}
public Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
listview.RefreshComplete();
super.handleMessage(msg);
}
};
@Override
public void onRefresh() {
new Thread(){
public void run() {
try {
Thread.sleep(1000);
handler.sendEmptyMessage(TRIM_MEMORY_BACKGROUND);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
}
}
点我下载