下拉刷新

以前弄的,边从网上找边写,在网上找到后,改了下,有些注释可能不对,因为我英语很烂

import java.text.SimpleDateFormat;
import java.util.Date;



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.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.View.MeasureSpec;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;

public class PullToRefreshListView extends ListView implements OnScrollListener{

    private String TAG = "tag";
    private Context con;
    private LayoutInflater mInflater;
    private ListView lv;
    private LinearLayout headView; //ListView的头部视图,用来下来刷新
    private ImageView arrowImg;  //下拉箭头
    private TextView tipsTv,lastUpdateTV; //提示和最后一次更新的
    private ProgressBar pb;
    private Animation animation, reverseAnimation;
    private final int RELEASE_TO_REFRESH = 1; //释放
    private final int PULL_TO_REFRESH = 2; //下拉刷新
    private final int REFRESHING = 3; //正在刷新
    private final int DONE = 4 ; //完成
    private final int LOADING = 5;
    // 实际的padding的距离与界面上偏移距离的比例
    private final int RATIO = 3;
    // 用于保证startY的值在一个完整的touch事件中只被记录一次
    private boolean isRecored;
    private int headContentWidth;
    private int headContentHeight;
    private int startY;
    private int firstItemIndex;
    private int state = 1;
    private boolean isBack;
    private OnRefreshListener refreshListener;
    private boolean isRefreshable;
    
    
    public PullToRefreshListView(Context con, ListView lv) {
        super(con);
        this.con = con;
        this.lv = lv;
        init();
    }
    public PullToRefreshListView(Context con, AttributeSet attr, ListView lv){
        super(con, attr);
        this.con = con;
        this.lv=lv;
        init();
    }
    
    //下面这些个方法是ListView 的下拉刷新用的     注释是我写的,可能不太对,
    private void init(){
        mInflater = LayoutInflater.from(con);
        headView = (LinearLayout) mInflater.inflate(R.layout.list_head, null);
        arrowImg = (ImageView) headView.findViewById(R.id.list_head_arrowImg);
        tipsTv = (TextView) headView.findViewById(R.id.list_head_tipsText);
        lastUpdateTV = (TextView) headView.findViewById(R.id.list_head_lastUpdateText);
        
        arrowImg.setMinimumHeight(50);
        arrowImg.setMinimumWidth(70);
        //计算head的高宽
        measureView(headView);
        headContentHeight = headView.getMeasuredHeight();
        headContentWidth = headView.getMeasuredWidth();
        //初始状态是隐藏headView的布局
        headView.setPadding(0, -1*headContentHeight, 0, 0);
                        //v data  isSelectable
        lv.addHeaderView(headView, null, false);
        //下拉动画                                //从0度一直旋转到-180度位置,
        animation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        animation.setInterpolator(new LinearInterpolator());
        animation.setDuration(250);
        animation.setFillAfter(true);
        
        //恢复动画
        reverseAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        reverseAnimation.setInterpolator(new LinearInterpolator());
        reverseAnimation.setDuration(200); //动画时间
        reverseAnimation.setFillAfter(true);// 设置为true,将坚持完成
        
        state = DONE;
        isRefreshable = false;
    }
                
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        
        
    }
    
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        firstItemIndex = firstVisibleItem;
        
    }
    //估量、预测控件的高和宽
    private void measureView(View child){
        
        ViewGroup.LayoutParams p = child.getLayoutParams();
        if(p == null){
            //为空就创建一个
            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        }                                                //spec  padding  childDimension
        int childWeightSpec = ViewGroup.getChildMeasureSpec(0, 0+0, p.width);
        int lpHeight = p.height;
        int childHeightSpec;
        if(lpHeight > 0){//有这个子类的高度,就创建一个精确的大小尺寸给它
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
        }else{//没有就默认为0                                  //size   mode
            childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY);
        }            //widthMeasureSpec  heightMeasureSpec
        child.measure(childWeightSpec, childHeightSpec);
    }
    //触屏事件  这是继承自ListView里的方法
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 用一个表示可刷新的状态来触发
        if(isRefreshable){
            switch (event.getAction()) {
            // 在down时候记录当前Y的位置
            case MotionEvent.ACTION_DOWN:
                if(firstItemIndex == 0 && !isRecored){
                    startY = (int) event.getY();
                    isRecored = true;
                }
                break;
            case MotionEvent.ACTION_UP:
                if(state != REFRESHING && state != LOADING){
                    if(state == DONE){
                        
                    }
                    //由下拉刷新状态,到done状态
                    if(state == PULL_TO_REFRESH){
                        state = DONE;
                        changeHeaderViewByState();
                    }
                    //由松开刷新状态,到done状态
                    if(state == RELEASE_TO_REFRESH){
                        state = REFRESHING;
                        changeHeaderViewByState();
                        onRefresh();
                    }
                }
                isRecored = false;
                isBack = false;
                break;
            case MotionEvent.ACTION_MOVE:
                int tempY = (int)event.getY();
                if(state != REFRESHING && state != LOADING && isRecored){
                    // 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
                    // 可以松手去刷新了
                    if(state == RELEASE_TO_REFRESH){
                        setSelection(0);
                        // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
                        if (((tempY - startY) / RATIO < headContentHeight)&& (tempY - startY) > 0) {
                        state = PULL_TO_REFRESH;
                        changeHeaderViewByState();
                        Log.v(TAG, "由松开刷新状态转变到下拉刷新状态");
                        }
                        // 一下子推到顶了
                        else if((tempY - startY) <= 0){
                            state = DONE;
                            changeHeaderViewByState();
                            Log.v(TAG, "由松开刷新状态转变到done状态");
                        }// 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步
                        else {
                            // 不用进行特别的操作,只用更新paddingTop的值就行了
                            }
                    }
                    // 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
                    if (state == PULL_TO_REFRESH) {
                        setSelection(0);
                        // 下拉到可以进入RELEASE_TO_REFRESH的状态
                        if ((tempY - startY) / RATIO >= headContentHeight) {
                            state = PULL_TO_REFRESH;
                            isBack = true;
                            changeHeaderViewByState();
                            Log.v(TAG, "由done或者下拉刷新状态转变到松开刷新");
                        }
                        // 上推到顶了
                        else if (tempY - startY <= 0) {
                            state = DONE;
                            changeHeaderViewByState();
                            Log.v(TAG, "由DOne或者下拉刷新状态转变到done状态");
                        }
                    }
                    // done状态下
                    if (state == DONE) {
                        if (tempY - startY > 0) {
                            state = PULL_TO_REFRESH;
                            changeHeaderViewByState();
                        }
                    }
                    // 更新headView的size
                    if (state == PULL_TO_REFRESH) {
                        headView.setPadding(0, -1 * headContentHeight
                                + (tempY - startY) / RATIO, 0, 0);
                    }
                    // 更新headView的paddingTop
                    if (state == PULL_TO_REFRESH) {
                        headView.setPadding(0, (tempY - startY) / RATIO
                                - headContentHeight, 0, 0);
                    }
                }
                break;
            default:
                break;
            }
        }
        return super.onTouchEvent(event);
    }
    //*/
    private void changeHeaderViewByState(){
        switch (state) {
        //松开刷新状态
        case RELEASE_TO_REFRESH:
            arrowImg.setVisibility(View.VISIBLE);
            pb.setVisibility(View.GONE);
            tipsTv.setVisibility(View.VISIBLE);
            lastUpdateTV.setVisibility(View.VISIBLE);
            tipsTv.setText("松开刷新");
            arrowImg.clearAnimation();
            arrowImg.startAnimation(animation);
            Log.v(TAG, "当前状态,松开刷新");
            break;
        //下拉刷新状态
        case PULL_TO_REFRESH:
            arrowImg.setVisibility(View.VISIBLE);
            pb.setVisibility(View.GONE);
             // 是由RELEASE_To_REFRESH状态转变来的
            //箭头反转向上
            if(isBack){
                isBack = false;
                arrowImg.clearAnimation();
                arrowImg.startAnimation(reverseAnimation);
                tipsTv.setText("下拉刷新");
                 Log.v(TAG, "当前状态,isBack true 下拉刷新");
            }else{
                tipsTv.setText("下拉刷新");
                 Log.v(TAG, "当前状态,isBack false 下拉刷新");
            }
            
            break;
        //正在刷新
        case REFRESHING:
            headView.setPadding(0, 0, 0, 0);
            arrowImg.setVisibility(View.GONE);
            arrowImg.clearAnimation();
            pb.setVisibility(View.VISIBLE);
            tipsTv.setText("正在刷新....");
            lastUpdateTV.setVisibility(View.VISIBLE);
            Log.v(TAG, "当前状态,正在刷新...");
            break;
        //刷新完成
        case DONE:
            headView.setPadding(0, -1*headContentHeight, 0, 0);
            arrowImg.clearAnimation();
            arrowImg.setImageResource(R.drawable.downicon);
//            arrowImg.setBackgroundDrawable(getResources().getDrawable(R.drawable.downicon));
            pb.setVisibility(View.GONE);
            tipsTv.setText("下拉刷新");
            lastUpdateTV.setVisibility(View.VISIBLE);
            Log.v(TAG, "当前状态,done");
            break;
        default:
            break;
        }
    }
    /*//public boolean onTouch(View v, MotionEvent event) {
        
        // 用一个表示可刷新的状态来触发
        if (isRefreshable) {
            switch (event.getAction()) {
            // 在down时候记录当前Y的位置
            case MotionEvent.ACTION_DOWN:
                if (firstItemIndex == 0 && !isRecored) { // 在第一个位置被按下,并且在没记录完Y值时
                    startY = (int) event.getY();
                    isRecored = true;
                }
                break;
            //松开的时候
            case MotionEvent.ACTION_UP:
                if (state != REFRESHING && state != LOADING) {
                    if (state == DONE) {

                    }
                    // 由下拉刷新状态,到done状态
                    if (state == PULL_TO_REFRESH) {
                        state = DONE;
                        changeHeaderViewByState();
                    }
                    // 由松开刷新状态,到done状态
                    if (state == RELEASE_TO_REFRESH) {
                        state = REFRESHING;
                        changeHeaderViewByState();
                        onRefresh();
                    }
                }
                isRecored = false;
                isBack = false;
                break;
            case MotionEvent.ACTION_MOVE:
                int tempY = (int) event.getY();
                if(!isRecored && firstItemIndex == 0){
                    isRecored = true;
                    startY = tempY;
                }
                if(state != REFRESHING && isRecored && state != LOADING){
                    // 保证在设置padding的过程中,当前的位置一直是在head,否则如果当列表超出屏幕的话,当在上推的时候,列表会同时进行滚动
                    // 可以松手去刷新了
                }
                break;
            default:
                break;
            }
            
        }
        return true;
  }
//*/
    public void onRefreshComplete(){
        state = DONE;
        SimpleDateFormat simpDate = new SimpleDateFormat("yyyy年MM月dd日   HH:mm");
        String date = simpDate.format(new Date());
        lastUpdateTV.setText("最近更新    "+date);
        changeHeaderViewByState();
    }
    public void onRefresh(){
        if(refreshListener != null){
            refreshListener.onRefresh();
        }
    }
    public void setOnRefreshListener(OnRefreshListener refreshListener){
        this.refreshListener = refreshListener;
        isRefreshable = true;
    }
    
    public interface OnRefreshListener{
        public void onRefresh();
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值