美文网首页
ViewDragHelper实现下拉刷新

ViewDragHelper实现下拉刷新

作者: aafa41d78d15 | 来源:发表于2017-08-31 18:24 被阅读0次

    前言

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

    实现步骤

    1.首先看一下布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" >
    
      <com.xsh.customviewstudy.view.PullToRefreshLayout
          android:id="@+id/refreshable_view"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent" >
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >
    
          <include layout="@layout/pull_to_refresh" />
    
          <ListView
              android:id="@+id/list_view"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:scrollbars="none" >
          </ListView>
        </LinearLayout>
      </com.xsh.customviewstudy.view.PullToRefreshLayout>
    
    </RelativeLayout>
    

    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实现下拉刷新

          本文链接:https://www.haomeiwen.com/subject/qvzqjxtx.html