美文网首页
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实现下拉刷新

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

  • ListView 实现下拉刷新

    ListView 实现下拉刷新ListView 实现上拉加载 我们先分析一下如何实现 ListView 下拉刷新。...

  • vant ui中 PullRefresh and List

    需求:展示(用户)账户的明细,需要懒加载和下拉刷新效果(List实现懒加载,PullRefresh实现下拉刷新) ...

  • UITableView 下拉刷新的实现

    UITableView下拉刷新的实现原理是自定义的下拉刷新控件KVO监听UITableView(UIScrollV...

  • Flutter 实现上拉加载更多、下拉刷新

    参考:ListView下拉刷新与加载更多 文章目录 相关文章推荐 实现效果 实现分析下拉刷新上拉加载更多 源码 相...

  • 下拉刷新与上滑加载更多

    实现下拉与上滑功能,主要依靠SwipeRefreshLayout组件。该组件自带下拉刷新功能。 下拉刷新 1.在布...

  • RecyclerViewRefresh

    采用RecyclerView和SwipeRefreshLayout实现下拉刷新和上拉自动加载更多 1.下拉刷新 2...

  • iOS开发 下拉刷新上拉加载更多详解

    下拉刷新(上拉加载更多)是大家经常用到的功能,本篇文章将带大家详细介绍下拉刷新原理,一步步实现下拉刷新效果。下拉刷...

  • Flutter 上拉加载、下拉刷新

    下拉刷新下拉刷新使用的是 RefreshIndicator组件来实现,使用伪代码如下: 在body中添加Refre...

  • Android面试整理

    RecyclerView的上拉加载、下拉刷新怎么实现?RecyclerView原生实现侧滑、拖动? 上拉加载、下拉...

网友评论

      本文标题:ViewDragHelper实现下拉刷新

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