[置顶] 下拉刷新ListView讲解,自定义PullToRefreshListView

思路


关于下拉刷新的ListView的实现,思路主要有两种:
1 . 用LinearLayout包裹一个refreshHeadView和一个listView , 触摸时通过改变refreshHeadView的LayoutParams参数的 topMargin来隐藏和显示refreshHeadView,lp.topMargin = - refreshHeadHeight 时,头部隐藏,lp.topMargin = 0 时,头部恰好完全出现。我的另外一篇博客实现了这个思路 :
[ http://blog.csdn.net/u010335298/article/details/50956995 ]
2 . 用ListView的addHeaderView方法,为ListView设置一个headView作为下拉刷新的view ,通过设置headView的topPadding来显示和隐藏headView , topPadding = - headHeight的时候,headView隐藏,topPadding = 0 时 ,头部恰好完全出现 。这篇博客就是用这种思路实现的。

效果

[置顶] 下拉刷新ListView讲解,自定义PullToRefreshListView_第1张图片

流程

为了方便讲解,我画了图来描述我的实现思路。
[置顶] 下拉刷新ListView讲解,自定义PullToRefreshListView_第2张图片

代码

下面是激动人心的代码啦~

package com.example.myapp.view;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.Scroller;
import android.widget.TextView;

import com.example.myapp.R;

/** * Created by zyr * DATE: 16-4-6 * Time: 下午4:02 * Email: [email protected] * * 通过listview addHeaderView来实现下拉刷新 */
public class CustomPullToRefreshListView2 extends ListView implements AbsListView.OnScrollListener {
    private Context mContext;

    private View headerView;

    private TextView headerTv;

    private int headerHeight;

    private Scroller mScroller;

    public static final int STATE_NONE  = 0;
    public static final int STATE_PULL_TO_REFRESH = 1; //下拉去刷新
    public static final int STATE_RELEASE_TO_REFRESH = 2; // 释放进行刷新
    public static final int STATE_REFRESHING = 3; // 正在刷新

    private int state = STATE_NONE;
    private int downY;

    public static final int DURATION = 500;
    private OnRefreshListener mOnRefreshListener;

    public interface OnRefreshListener{
        void onDownPullRefresh();
    }

    /************************ 构造****************************************/

    public CustomPullToRefreshListView2(Context context) {
        this(context, null);
    }

    public CustomPullToRefreshListView2(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomPullToRefreshListView2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;

        initScroller();
        initHeaderView();
        setOnScrollListener(this);
    }

    private void initScroller() {
        mScroller = new Scroller(getContext(), new DecelerateInterpolator());
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if(mScroller.computeScrollOffset()){
            headerView.setPadding(0, mScroller.getCurrY(), 0, 0);
        }
    }

    private void initHeaderView() {
        headerView =  View.inflate(getContext(), R.layout.header_listview, null);
        headerTv = (TextView) headerView.findViewById(R.id.tvHead);
        headerView.measure(0, 0); // 系统会帮我们测量出headerView的高度
        headerHeight = headerView.getMeasuredHeight();
        Log.d("zyr", "--------------------headerHeight :" + headerHeight);
        headerView.setPadding(0, -headerHeight, 0, 0);
        invalidate();
        Log.d("zyr", "----------------------headerPaddingTop :" + headerView.getPaddingTop());
        super.addHeaderView(headerView, null, false);
    }

    /************************** Scroll******************************/
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

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

    /*************************** Touch***************************************/
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN :
                downY = (int) ev.getY();
                break;
            case MotionEvent.ACTION_MOVE :
                int moveY = (int) ev.getY();
                // 移动中的y - 按下的y = 间距.
                int diff = (moveY - downY) / 2;
                // -头布局的高度 + 间距 = paddingTop
                int paddingTop = -headerHeight + diff;
                // 如果: 第一个可见,向下拉
                if (getFirstVisiblePosition() == 0
                        &&  diff > 0) {
                    if (paddingTop > 0 ) { // 完全显示了.
                        Log.i("zyr", "松开刷新");
                        state = STATE_RELEASE_TO_REFRESH;
                        refreshHeaderView();
                    } else if (paddingTop < 0 ) { // 没有显示完全
                        Log.i("zyr", "下拉刷新");
                        state = STATE_PULL_TO_REFRESH;
                        refreshHeaderView();
                    }
                    // 下拉头布局
                    Log.d("zyr","--------------paddingTop:" + paddingTop);
                    headerView.setPadding(0, paddingTop, 0, 0);
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP :
                // 判断当前的状态是松开刷新还是下拉刷新
                if (state == STATE_RELEASE_TO_REFRESH) {
                    Log.i("zyr", "刷新数据.");
                    // 把头布局设置为完全显示状态
                    mScroller.startScroll(0,headerView.getPaddingTop(),0,0-headerView.getPaddingTop(),DURATION);
                    postInvalidate();
                    // 进入到正在刷新中状态
                    state = STATE_REFRESHING;
                    refreshHeaderView();

                    if (mOnRefreshListener != null) {
                        mOnRefreshListener.onDownPullRefresh(); // 调用使用者的监听方法
                    }
                } else if (state == STATE_PULL_TO_REFRESH) {
                    // 隐藏头布局
                    mScroller.startScroll(0,headerView.getPaddingTop(),0,- headerHeight -headerView.getPaddingTop(),DURATION);
                    postInvalidate();
                }
                break;
            default :
                break;
        }
        return super.onTouchEvent(ev);
    }
    /** * 根据currentState刷新头布局的状态 */
    private void refreshHeaderView() {
        switch (state) {
            case STATE_PULL_TO_REFRESH : // 下拉刷新状态
                headerTv.setText("下拉刷新");
                break;
            case STATE_RELEASE_TO_REFRESH : // 松开刷新状态
                headerTv.setText("松开刷新");
                break;
            case STATE_REFRESHING : // 正在刷新中状态
                headerTv.setText("正在刷新中...");
                break;
            default :
                break;
        }
    }

    /** * 隐藏头布局 */
    public void hideHeaderView() {
        post(new Runnable() {
            @Override
            public void run() {
                mScroller.startScroll(0,headerView.getPaddingTop(),0,- headerHeight -headerView.getPaddingTop(),DURATION);
                postInvalidate();
                headerTv.setText("下拉刷新");
                state = STATE_NONE;
            }
        });
    }

    /** * 设置刷新监听事件 * * @param listener */
    public void setOnRefreshListener(OnRefreshListener listener) {
        mOnRefreshListener = listener;
    }

}

header_listiew.xml

<?xml version="1.0" encoding="utf-8"?><!-- ListView的头部 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical">

    <!-- 内容 -->

    <RelativeLayout  android:id="@+id/head_contentLayout" android:layout_width="fill_parent" android:layout_height="50dp" android:gravity="center">
        <TextView  android:id="@+id/tvHead" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/pull_to_refresh_pull_label" android:textColor="@color/black" android:textSize="15.5sp" android:textStyle="bold" />
    </RelativeLayout>



</LinearLayout>

activity调用

  listView = (CustomPullToRefreshListView2) findViewById(R.id.listview);
  for(int i=0;i<20;i++){
       strings.add("zyr" + i);
  }
  commonAdapter = new CommonAdapter(this,strings);
  listView.setAdapter(commonAdapter);
  listView.setOnRefreshListener(new CustomPullToRefreshListView2.OnRefreshListener() {
       @Override
       public void onDownPullRefresh() {
           new Thread(new Runnable() {
               @Override
               public void run() {
                  try {
                      Thread.sleep(1000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                     listView.hideHeaderView();
                  }
              }).start();
      }
 });

你可能感兴趣的:(ListView)