ViewDragHelper实现下拉刷新

前言

使用ViewDragHelper实现肯定可以实现下拉刷新,而且可以通过这种场景可以举一反三出很多其他的场景。

实现步骤

1.首先看一下布局文件




  

    

      

      
      
    
  


PullToRefreshLayout是个ViewGroup,它下面有一个子类,这个子类下又包含两个子类,一个就是head部分,一个就是ListView部分

2.接下来看PullToRefreshLayout的实现

import android.content.Context;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.xsh.customviewstudy.R;

public class PullToRefreshLayout extends LinearLayout {
    private final String TAG="PullToRefreshLayout";
    /**
     * 下拉状态
     */
    public static final int STATUS_PULL_TO_REFRESH = 0;

    /**
     * 释放立即刷新状态
     */
    public static final int STATUS_RELEASE_TO_REFRESH = 1;

    /**
     * 正在刷新状态
     */
    public static final int STATUS_REFRESHING = 2;

    /**
     * 刷新完成或未刷新状态
     */
    public static final int STATUS_REFRESH_FINISHED = 3;
    

    /**
     * 下拉头的View
     */
    private View header;

    /**
     * 刷新时显示的进度条
     */
    private ProgressBar progressBar;

    /**
     * 指示下拉和释放的文字描述
     */
    private TextView description;

    /**
     * 下拉头的布局参数
     */
    private MarginLayoutParams headerLayoutParams;

    /**
     * 当前处理什么状态,可选值有STATUS_PULL_TO_REFRESH, STATUS_RELEASE_TO_REFRESH,
     * STATUS_REFRESHING 和 STATUS_REFRESH_FINISHED
     */
    private int currentStatus = STATUS_REFRESH_FINISHED;;

    
    /**
     * 记录上一次的状态是什么,避免进行重复操作
     */
    private int lastStatus = currentStatus;

    /**
     * 用于处理事件分发的mDragger 
     */
    private ViewDragHelper mDragger;

    /**
     * 需要去下拉刷新的ListView
     */
    private AbsListView listView;
    
    private LinearLayout pullLayout;
    /**
     * 下拉头的高度
     */
    private int hideHeaderHeight;
    
    /**
     * 当前滑动的距离 
     */
    private int currentTop;
    
    /**
     * 允许滑动的最大距
     */
    private int maxDragHeight;
    /**
     * 是否加载过
     */
    private boolean loadOnce=false;
    
    private boolean isTouch=false;
    
    private PullToRefreshListener pullToRefreshListener;
    
    public PullToRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if(changed && !loadOnce){
            maxDragHeight=getMeasuredHeight()/2;
            hideHeaderHeight = -header.getHeight();
            headerLayoutParams = (MarginLayoutParams) pullLayout.getLayoutParams();
            headerLayoutParams.topMargin = hideHeaderHeight;
            loadOnce = true;
        }
    }
    
    @Override
    public void computeScroll() {
        super.computeScroll();
        if(mDragger.continueSettling(true)){
            invalidate();
        }
    }
    
    /**
     * 设置刷新回调接口
     * @param listener
     */
    public void setPullToRefreshistener(PullToRefreshListener listener){
        this.pullToRefreshListener=listener;
    }
    
    /**
     * 完成刷新
     */
    public void finishPullToRefresh(){
        currentStatus=STATUS_REFRESH_FINISHED;
        mDragger.smoothSlideViewTo(pullLayout, 0, hideHeaderHeight);
        invalidate();
    }
    
    /**
     * 初始化view 
     */
    private void init(){
        pullLayout=(LinearLayout) getChildAt(0);
        listView = (AbsListView) pullLayout.getChildAt(1);
        header = pullLayout.getChildAt(0);
        progressBar = (ProgressBar) header.findViewById(R.id.progress_bar);
        description = (TextView) header.findViewById(R.id.description);
        
        mDragger=ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
            /**
             * 进行捕获拦截,那些View可以进行drag操作
             * @param childView
             * @param position
             * @return  直接返回true,拦截所有的VIEW
             */
            @Override
            public boolean tryCaptureView(View childView, int position) {
                Log.i(TAG, "tryCaptureView");
                isTouch=true;
                return childView==pullLayout && isTop() ;
            }
            
            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                Log.i(TAG, "clampViewPositionVertical: top="+top+"dy="+dy+"hideHeaderHeight="+hideHeaderHeight+"maxDragHeight="+maxDragHeight);
                if(top<=hideHeaderHeight){
                    return hideHeaderHeight;
                }else if(top>maxDragHeight){
                    return maxDragHeight;
                }
                return top;
            }
             @Override
            public void onViewReleased(View releasedChild, float xvel,  float yvel) {
                 Log.i(TAG, "onViewReleased");
                super.onViewReleased(releasedChild, xvel, yvel);
                if (releasedChild == pullLayout){
                    isTouch=false;
                    if (currentStatus == STATUS_RELEASE_TO_REFRESH ) {
                        // 松手时如果是释放立即刷新状态,就去调用正在刷新的任务
                        currentStatus = STATUS_REFRESHING;
                        updateHeadView();
                        mDragger.settleCapturedViewAt(0,0);
                        invalidate();
                        if(pullToRefreshListener!=null){
                            pullToRefreshListener.onRefresh();
                        }
                    }else if(currentStatus == STATUS_PULL_TO_REFRESH ){
                        mDragger.settleCapturedViewAt(0,hideHeaderHeight);
                        invalidate();
                    }else if(currentStatus == STATUS_REFRESHING){
                        mDragger.settleCapturedViewAt(0,0);
                        invalidate();
                    }

                }
            }
             
             @Override
            public void onViewPositionChanged(View changedView, int left,
                    int top, int dx, int dy) {
                super.onViewPositionChanged(changedView, left, top, dx, dy);
                Log.i(TAG, "onViewPositionChanged: top="+top);
                currentTop=top;
                if (isTouch && currentStatus != STATUS_REFRESHING){
                    if (currentTop <0) {
                        currentStatus = STATUS_PULL_TO_REFRESH;
                    } else {
                        currentStatus = STATUS_RELEASE_TO_REFRESH;
                    }
                    updateHeadView();
                    lastStatus=currentStatus;
                }
            }
             @Override
            public int getViewVerticalDragRange(View child) {
                 return maxDragHeight;
            }
            
        });
        
    }
    
    private void updateHeadView(){
        if(lastStatus!=currentStatus){
            if (currentStatus == STATUS_PULL_TO_REFRESH) {
                description.setText(getResources().getString(R.string.pull_to_refresh));
                progressBar.setVisibility(View.GONE);
            } else if (currentStatus == STATUS_RELEASE_TO_REFRESH) {
                description.setText(getResources().getString(R.string.release_to_refresh));
                progressBar.setVisibility(View.GONE);
            } else if (currentStatus == STATUS_REFRESHING) {
                description.setText(getResources().getString(R.string.refreshing));
                progressBar.setVisibility(View.VISIBLE);
            }
        }

    }
    private boolean isTop(){
        return listView.getFirstVisiblePosition() == 0
                && getScrollY() <= listView.getMeasuredHeight();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mDragger.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mDragger.processTouchEvent(event);
        return true;
    }
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        init();
    }
    
    public interface PullToRefreshListener {
        /**
         * 下拉刷新时调用
         */
        void onRefresh();
        
        /**
         * 上拉加载更多的刷新
         */
//      void onLoadMoreRefresh();

    }

}

1.protected void onFinishInflate() :实例化各个子View,比如LinearLayout,ListView,progressBar等等
实例化ViewDragHelper

2.protected void onLayout(boolean changed, int l, int t, int r, int b) : 把head隐藏起来

3.其他部分就没什么好的,so easy

源码参考我的github地址

参考文章

http://blog.csdn.net/liuwang521/article/details/52764520

你可能感兴趣的:(ViewDragHelper实现下拉刷新)