ListView 下拉更新

来源:互联网 发布:旋转变换矩阵 编辑:程序博客网 时间:2024/05/16 14:03
package com.example.listview;


import java.util.Date;


import android.content.Context;
import android.util.AttributeSet;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView.OnScrollListener;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;


public class MyListView extends ListView implements OnScrollListener
{
/** 手指滑动距离和下拉的比例 */
private final static int ROTA = 3;
private final static int DOWN = 0;
/** 下拉刷新的状态 */
private final static int PULL_TO_REFRESH = 1;
/** 下拉刷新的状态 */
private final static int RELESE_TO_REFRESH = 2;
/** 下拉刷新的状态 */
private final static int REFRESHING = 3;
private OnRefreshListener reListener;
private LayoutInflater inflater;
private LinearLayout head;
private ImageView arrowImage;
private ProgressBar progressBar;
private TextView refreshTips;
private TextView updateTime;
/** 将箭头从朝下变为朝上*/
private RotateAnimation animation;
/** 将箭头从朝上变为朝下*/
private RotateAnimation reserverAnimation;
/** headView的宽度*/
private int headWidth;
/**headView的高度*/
private int headHeight;
/**是否注册了refresh的监听器*/
private boolean refreshAble; 
/**是否是从释放刷新到下拉刷新*/
private boolean isBack;

/**刷新条的状态*/
private int state;
/**開頭位置*/
private int firstVisibleIndex;

/**判断是否记录了startY*/
private boolean isRecord;
private int startY;


public MyListView(Context context)
{
super(context);
init(context);
}


public MyListView(Context context, AttributeSet attribute)
{
super(context, attribute);
init(context);
}


/**
*  初始化个控件
* @param context
*/
private void init(Context context)
{
setCacheColorHint(getResources().getColor(R.color.transparent));
inflater = LayoutInflater.from(context);
head = (LinearLayout) inflater.inflate(R.layout.refresh_head, null);
arrowImage = (ImageView) head
.findViewById(R.id.refresh_head_arrow_image);
progressBar = (ProgressBar) head
.findViewById(R.id.refresh_head_progress_bar);
refreshTips = (TextView) head.findViewById(R.id.refresh_head_tips);
updateTime = (TextView) head
.findViewById(R.id.refresh_head_update_time);// 实例化个组件
measureView(head);
headHeight = head.getMeasuredHeight();
headWidth = head.getMeasuredWidth();
head.setPadding(0, -headHeight, 0, 0);
head.invalidate();// 刷新界面
this.addHeaderView(head, null, false);
this.setOnScrollListener(this);
animation = new RotateAnimation(0, -180,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
animation.setInterpolator(new LinearInterpolator());
animation.setDuration(200);
animation.setFillAfter(true);
reserverAnimation = new RotateAnimation(-180, 0,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
reserverAnimation.setInterpolator(new LinearInterpolator());
reserverAnimation.setDuration(200);
reserverAnimation.setFillAfter(true);
state = DOWN;
refreshAble = false;
isBack = false;
isRecord = false;
}


@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount)
{
firstVisibleIndex = firstVisibleItem;
}


@Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{
// TODO Auto-generated method stub


}


@Override
public boolean onTouchEvent(MotionEvent event)
{
if (refreshAble)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN :
{
if (firstVisibleIndex == 0 && !isRecord)
{
startY = (int) event.getY();
isRecord = true;
}
break;
}
case MotionEvent.ACTION_UP :
{
if (state != REFRESHING)
{
if (state == DOWN);
if (state == PULL_TO_REFRESH)
{
state = DOWN;
setHeaderByState();
}
if (state == RELESE_TO_REFRESH)
{
state = REFRESHING;
setHeaderByState();
onRefresh();
}
}
isBack = false;
isRecord = false;
break;
}
case MotionEvent.ACTION_MOVE :
{
// move的到的位置的Y
int tempY = (int) event.getY();
if (firstVisibleIndex == 0 && !isRecord)
{
startY = (int) event.getY();
isRecord = true;
}

// 可以進行下拉更新
if (state != REFRESHING && isRecord)
{
// 第2步運行
if (state == PULL_TO_REFRESH)
{
// 返回條目第一位
setSelection(0);
// 当下拉位置比例大于头部高度
if ((tempY - startY) / ROTA >= headHeight)
{
// 改变状态为2
state = RELESE_TO_REFRESH;
isBack = true;
setHeaderByState();

} else if ((tempY - startY) < 0)
{
// 移回
state = DOWN;
setHeaderByState();
}
}
// 第3步運行
if (state == RELESE_TO_REFRESH)
{
// 返回條目第一位
setSelection(0);
if ((tempY - startY) / ROTA < headHeight
&& tempY - startY > 0)
{
// 改变状态为1
state = PULL_TO_REFRESH;
setHeaderByState();

} else if ((tempY - startY) <= 0)
{
// 移回
state = DOWN;
setHeaderByState();
}
}

// 第一步運行
if (state == DOWN)
{
// 移动位置Y大于开始位置Y
if (tempY - startY > 0)
{
// 改变状态为1
state = PULL_TO_REFRESH;
setHeaderByState();
}
}

if (state == PULL_TO_REFRESH)
{
head.setPadding(0, (tempY - startY) / ROTA
- headHeight, 0, 0);
}
if (state == RELESE_TO_REFRESH)
{
head.setPadding(0, (tempY - startY) / ROTA
- headHeight, 0, 0);
}
}
break;
}
}
}


return super.onTouchEvent(event);
}


/**
*  通过state设置刷新头
*/
private void setHeaderByState()
{
switch (state)
{
case DOWN :
{
head.setPadding(0, -headHeight, 0, 0);
progressBar.setVisibility(View.GONE);// 这个必须在后者前面
arrowImage.clearAnimation();
arrowImage.setVisibility(View.VISIBLE);
arrowImage.setImageResource(R.drawable.arrowdown);
refreshTips.setText("下拉刷新");
break;
}
case PULL_TO_REFRESH :
{
// 正在下拉中
progressBar.setVisibility(View.GONE);
arrowImage.clearAnimation();
arrowImage.setVisibility(View.VISIBLE);
refreshTips.setText("下拉刷新");
if (isBack)
{
isBack = false;
// 箭头转向下
arrowImage.startAnimation(reserverAnimation);
}
break;
}


case RELESE_TO_REFRESH :
{
arrowImage.clearAnimation();
arrowImage.startAnimation(animation);
refreshTips.setText("松开刷新");
break;
}
case REFRESHING :
{
head.setPadding(0, 0, 0, 0);
arrowImage.clearAnimation();
arrowImage.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
refreshTips.setText("正在刷新");
break;
}
}
}


/**
*  测量View
* @param child
*/
private void measureView(View child)
{
ViewGroup.LayoutParams childParams = (ViewGroup.LayoutParams) child
.getLayoutParams();
if (childParams == null)
childParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0,
childParams.width);
int childHeightSpec = childParams.height;
if (childHeightSpec > 0)
childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSpec,
MeasureSpec.EXACTLY);
else
childHeightSpec = MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED);
child.measure(childWidthSpec, childHeightSpec);
}


/**
*  回调接口
* @author 1.12
*
*/
public interface OnRefreshListener
{
public void onRefresh();
}


/**
*  注册监听器的方法
* @param listener
*/
public void setOnRefreshListener(OnRefreshListener listener)
{
this.reListener = listener;
refreshAble = true;
}


/**
*  在此回调接口中的方法
*/
private void onRefresh()
{
if (reListener != null)
reListener.onRefresh();
}


/**
*  refresh完成调用的方法
*/
public void onRefreshComplete()
{
state = DOWN;
setHeaderByState();
updateTime.setText("上次更新时间:" + new Date().toLocaleString());
}


public void setAdapter(BaseAdapter adapter)
{
updateTime.setText("上次更新时间:" + new Date().toLocaleString());
super.setAdapter(adapter);
}
}
原创粉丝点击