使用SwipeRefreshLayout实现recycleview下拉刷新上拉加载

来源:互联网 发布:如何用字符串表示json 编辑:程序博客网 时间:2024/05/01 12:11

http://blog.csdn.net/cj_286/article/details/52767070

谷歌在v4包下提供了一个SwipeRefreshLayout来实现RecyclerView的下拉刷新,但是此类并不提供上拉加载更多的一个功能,网上有很多的博客实现了上拉加载,但是上拉的效果图和之前的一样,今天我就实现类似于SwipeRefreshLayout刷新的效果图。圆形进度条的实现类MaterialProgressDrawable,之后解决的就是什么时候让圆形进度条显示,如何让圆形进度条随着手指上下滑动。
就是在dispatchTouchEvent分发事件的时候,不断的去检测RecyclerView是否已经下拉到底部了,这时就让圆形进度条显示,如何再向上滑动就向上滑动,向下滑动就向下滑动,松开就计算滑动的高度是否符合加载的高度,符合就固定圆形进度条让其滚动,不符合就消失。

判断是否已经到底部了

[java] view plain copy
  1. private boolean canPullUp() {  
  2.         RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager();  
  3.         mLastVisiblePosition = getLastVisibleItemPosition();  
  4.         int count = mRecyclerView.getAdapter().getItemCount();  
  5.         if (0 == count) {  
  6.             // 没有item的时候可以上拉加载  
  7.             return true;  
  8.         } else if (mLastVisiblePosition == (count - 1)) {  
  9.             // 滑到底部了可以上拉加载  
  10.             if (lm.findViewByPosition(count - 1).getBottom() <= getMeasuredHeight()) {  
  11.                 return true;  
  12.             }  
  13.         }  
  14.         return false;  
  15.     }  


不断检测滑动的位置,显示圆形进度条的位置
[java] view plain copy
  1. @Override  
  2.     public boolean dispatchTouchEvent(MotionEvent event) {  
  3.   
  4.         if(!mIsAllowLoadMore) return super.dispatchTouchEvent(event);  
  5.   
  6.         switch (event.getAction()) {  
  7.             case MotionEvent.ACTION_DOWN:  
  8.                 mStartY = (int) event.getRawY();  
  9.                 break;  
  10.             case MotionEvent.ACTION_MOVE:  
  11.   
  12.                 if (!mStart) {  
  13.                     //如果不满足上拉的条件就直接分发事件  
  14.                     if(!canPullUp()){  
  15.                         return super.dispatchTouchEvent(event);  
  16.                     }  
  17.                     if (canPullUp() && !mIsCanScoll) {  
  18.                         showRefreshArrow();  
  19.                         mStartY = (int) event.getRawY();  
  20.                         mIsCanScoll = true;  
  21.                     } else {  
  22.                         //mStartY = (int) event.getRawY();  
  23.                         //hideRefreshArrow();  
  24.                         //hide();  
  25.                     }  
  26.                     if (mVisibleCanScoll) {  
  27.                         int endY = (int) event.getRawY();  
  28.                         int offset = mStartY - endY;  
  29.                         //System.out.println("----------------------offset:" + offset);  
  30.                         LayoutParams lp = (LayoutParams) mImageView.getLayoutParams();  
  31.                         int bottomMargin = lp.bottomMargin;  
  32.                         bottomMargin += offset;  
  33.                         if (bottomMargin >= PULL_IMAGE_SIZE_PX_MAX) {  
  34.                             bottomMargin = PULL_IMAGE_SIZE_PX_MAX;  
  35.                         }  
  36.   
  37.                         if (bottomMargin <= -PULL_IMAGE_SIZE_PX) {  
  38.                             bottomMargin = -PULL_IMAGE_SIZE_PX;  
  39.   
  40.                         }  
  41.                         lp.setMargins(lp.leftMargin, lp.topMargin, lp.rightMargin, bottomMargin);  
  42.                         mImageView.setLayoutParams(lp);  
  43.   
  44.                         rotateAniamtor(bottomMargin * ROTATE_ANIM_ANGLE_PER);  
  45.   
  46.                         mStartY = endY;  
  47.                     }  
  48.   
  49.                     LayoutParams lp = (LayoutParams) mImageView.getLayoutParams();  
  50.                     //如果按住上拉时,上拉箭头向下滑动的时候事件不应分发  
  51.                     if(mVisable && lp.bottomMargin > -PULL_IMAGE_SIZE_PX){  
  52.                         mIsDispatch = false;  
  53.                     }else if(mVisable && lp.bottomMargin == -PULL_IMAGE_SIZE_PX){//等到上拉箭头被隐藏掉的时候在分发事件  
  54.                         mIsDispatch = true;  
  55.                     }  
  56.   
  57.                     //是否分发事件  
  58.                     if(!mIsDispatch) {  
  59.                         return false;  
  60.                     }  
  61.                     else {  
  62.                         return super.dispatchTouchEvent(event);  
  63.                     }  
  64.                 }  
  65.                 break;  
  66.   
  67.             case MotionEvent.ACTION_UP:  
  68.             case MotionEvent.ACTION_CANCEL:  
  69.   
  70.                 if (!mStart) {  
  71.   
  72.                     if (mVisibleCanScoll) {  
  73.                         LayoutParams lp = (LayoutParams) mImageView.getLayoutParams();  
  74.                         if (lp.bottomMargin >= PULL_IMAGE_SIZE_PX_EXECUTE) {  
  75.                             //lp.setMargins(lp.leftMargin, lp.topMargin, lp.rightMargin, PULL_IMAGE_SIZE_PX / 3 * 2);  
  76.                             //mImageView.setLayoutParams(lp);  
  77.                             //start();  
  78.                             getValueToTranslation();  
  79.                             mPrepareAnimation = true;  
  80.   
  81.                             if (mOnPullListener != null) {  
  82.                                 mOnPullListener.onLoadMore(this);  
  83.                             }  
  84.                         } else {  
  85.   
  86.                             hideArrow();  
  87.   
  88.                         }  
  89.                     }  
  90.                     if (!mStart && !mPrepareAnimation)  
  91.                         hideArrow();  
  92.                 }  
  93.   
  94.                 mIsCanScoll = false;  
  95.   
  96.                 break;  
  97.         }  
  98.   
  99.         return super.dispatchTouchEvent(event);  
  100.     }  



当上拉松开时会有一个滑动的动画
[java] view plain copy
  1. /** 
  2.      * 执行平移动画 
  3.      * @param from 
  4.      * @param to 
  5.      */  
  6.     private void translationTo(int from,int to,final boolean isShow){  
  7.         //1.调用ofInt(int...values)方法创建ValueAnimator对象  
  8.         ValueAnimator mAnimator = ValueAnimator.ofInt(from,to);  
  9.         //2.为目标对象的属性变化设置监听器  
  10.         mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
  11.   
  12.             @Override  
  13.             public void onAnimationUpdate(ValueAnimator animation) {  
  14.                 // 3.为目标对象的属性设置计算好的属性值  
  15.                 int animatorValue = (int)animation.getAnimatedValue();  
  16.                 MarginLayoutParams marginLayoutParams = (MarginLayoutParams) mImageView.getLayoutParams();  
  17.                 marginLayoutParams.bottomMargin = animatorValue;  
  18.                 mImageView.setLayoutParams(marginLayoutParams);  
  19.             }  
  20.         });  
  21.         mAnimator.addListener(new AnimatorListenerAdapter() {  
  22.             @Override  
  23.             public void onAnimationEnd(Animator animation) {  
  24.                 super.onAnimationEnd(animation);  
  25.                 if(isShow){  
  26.                     start();  
  27.                     mPrepareAnimation = false;  
  28.                 }else{  
  29.                     hideRefreshArrow();  
  30.                     hide();  
  31.                 }  
  32.   
  33.             }  
  34.         });  
  35.         //4.设置动画的持续时间、是否重复及重复次数等属性  
  36.         mAnimator.setDuration(100);  
  37.         //mAnimator.setRepeatCount(3);  
  38.         mAnimator.setRepeatMode(ValueAnimator.INFINITE);  
  39.         //5.为ValueAnimator设置目标对象并开始执行动画  
  40.         mAnimator.setTarget(mImageView);  
  41.         mAnimator.start();  
  42.     }  



圆形进度条随着滑动的距离产生旋转动画
[html] view plain copy
  1. /**  
  2.      * 旋转动画效果  
  3.      */  
  4.     private void rotateAniamtor(float from){  
  5.   
  6.         ObjectAnimator mAnimatorRotate = ObjectAnimator.ofFloat(mImageView, "rotation",from,from + 1);  
  7.         mAnimatorRotate.setRepeatMode(Animation.INFINITE);  
  8.         mAnimatorRotate.setRepeatCount(1);  
  9.         mAnimatorRotate.setDuration(10);  
  10.         mAnimatorRotate.start();  
  11.     }  



圆形进度条的阴影背景实现
[java] view plain copy
  1. /** 
  2.      * mImageView的背景 
  3.      */  
  4.     private Drawable getShapeDrawable() {  
  5.         /** 
  6.          * <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > 
  7.          <!-- 第一层  上部和左部偏移一定距离--> 
  8.          <item 
  9.          > 
  10.          <shape android:shape="oval"> 
  11.          <solid android:color="#f5f5f5" /> 
  12.          <!-- 描边 --> 
  13.          <stroke 
  14.          android:width="0.5dp" 
  15.          android:color="#99f5f5f5" /> 
  16.          </shape> 
  17.          </item> 
  18.          <!-- 第二层 下部和有部偏移一定距离--> 
  19.          <item 
  20.          android:left="2dp" 
  21.          android:top="2dp" 
  22.          android:bottom="2dp" 
  23.          android:right="2dp"> 
  24.          <shape android:shape="oval"> 
  25.          <solid android:color="#ffffff" /> 
  26.          <!-- 描边 --> 
  27.          <!--<stroke android:width="0.33dp" android:color="#dedede" />--> 
  28.          </shape> 
  29.          </item> 
  30.          </layer-list> 
  31.          */  
  32.         //代码实现  
  33.         GradientDrawable gradientDrawable = new GradientDrawable();  
  34.         gradientDrawable.setShape(GradientDrawable.OVAL);  
  35.         gradientDrawable.setColor(Color.parseColor("#f5f5f5"));  
  36.         int stroke = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0.5f, getContext().getResources().getDisplayMetrics());  
  37.         gradientDrawable.setStroke(stroke,Color.parseColor("#99f5f5f5"));  
  38.         GradientDrawable gradientDrawable2 = new GradientDrawable();  
  39.         gradientDrawable2.setShape(GradientDrawable.OVAL);  
  40.         gradientDrawable2.setColor(Color.parseColor("#ffffff"));  
  41.         LayerDrawable drawable = new LayerDrawable(new Drawable[]{gradientDrawable,gradientDrawable2});  
  42.         int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getContext().getResources().getDisplayMetrics());  
  43.         drawable.setLayerInset(1,padding,padding,padding,padding);////第一个参数1代表数组的第二个元素,为白色  
  44.         return drawable;  
  45.     }  


好了,源码就分析到这,如果发现bug或者有任何意见欢迎留言。


源码:

[java] view plain copy
  1. package com.cj.recyclerview.refresh;  
  2.   
  3. import android.animation.Animator;  
  4. import android.animation.AnimatorListenerAdapter;  
  5. import android.animation.ObjectAnimator;  
  6. import android.animation.ValueAnimator;  
  7. import android.content.Context;  
  8. import android.content.res.Resources;  
  9. import android.graphics.Color;  
  10. import android.graphics.drawable.Drawable;  
  11. import android.graphics.drawable.GradientDrawable;  
  12. import android.graphics.drawable.LayerDrawable;  
  13. import android.support.annotation.ColorRes;  
  14. import android.support.v4.widget.SwipeRefreshLayout;  
  15. import android.support.v7.widget.GridLayoutManager;  
  16. import android.support.v7.widget.LinearLayoutManager;  
  17. import android.support.v7.widget.RecyclerView;  
  18. import android.support.v7.widget.StaggeredGridLayoutManager;  
  19. import android.util.AttributeSet;  
  20. import android.util.TypedValue;  
  21. import android.view.MotionEvent;  
  22. import android.view.View;  
  23. import android.view.ViewGroup;  
  24. import android.view.animation.Animation;  
  25. import android.view.animation.DecelerateInterpolator;  
  26. import android.widget.ImageView;  
  27. import android.widget.RelativeLayout;  
  28.   
  29. /** 
  30.  * Created by chenj on 2016/9/28. 
  31.  */  
  32. public class PullRefreshLayout extends RelativeLayout {  
  33.   
  34.     private int[] colors = {  
  35.             0xFFFF00000xFFFF7F000xFFFFFF000xFF00FF00  
  36.             , 0xFF00FFFF0xFF0000FF0xFF8B00FF};  
  37.   
  38.     private final int CIRCLE_BG_LIGHT = 0xFFFAFAFA;  
  39.   
  40.     private MaterialProgressDrawable mProgress;  
  41.   
  42.     private ValueAnimator mValueAnimator;  
  43.   
  44.     private boolean mStart = false;  
  45.   
  46.     private boolean mVisable = false;  
  47.   
  48.     private static final int PULL_IMAGE_SIZE = 40;  
  49.     private static int PULL_IMAGE_SIZE_PX;//上拉View的大小(像素)  
  50.     private static int PULL_IMAGE_SIZE_PX_MAX ;//最大拉动的距离  
  51.     private static int PULL_IMAGE_SIZE_PX_EXECUTE ;//拉动到什么位置开始执行  
  52.     private static int PULL_IMAGE_SIZE_PX_EXECUTE_REFRESH ;//刷新是所在的位置  
  53.     private static float ROTATE_ANIM_ANGLE_PER;//根据最大距离计算旋转角度的比列  
  54.   
  55.     private ImageView mImageView;  
  56.     private boolean mIsFirst;  
  57.   
  58.     private int mStartY, mLastY;  
  59.     private RecyclerView mRecyclerView;  
  60.     //private int mFirstVisiblePosition;  
  61.     private int mLastVisiblePosition;  
  62.   
  63.     private boolean mIsCanScoll;  
  64.   
  65.     private boolean mVisibleCanScoll;  
  66.   
  67.     private boolean mPrepareAnimation;//准备执行动画  
  68.   
  69.     private boolean mIsAllowLoadMore = true;//是否可以上拉刷新  
  70.   
  71.     private boolean mIsDispatch = true;//是否分发事件  
  72.   
  73.     public PullRefreshLayout(Context context) {  
  74.         this(context, null);  
  75.     }  
  76.   
  77.     public PullRefreshLayout(Context context, AttributeSet attrs) {  
  78.         this(context, attrs, 0);  
  79.     }  
  80.   
  81.     public PullRefreshLayout(Context context, AttributeSet attrs, int defStyleAttr) {  
  82.         super(context, attrs, defStyleAttr);  
  83.   
  84.   
  85.     }  
  86.   
  87.     /** 
  88.      * 是否允许下拉加载更多 
  89.      * @param allowLoadMore 
  90.      */  
  91.     public void setAllowLoadMore(boolean allowLoadMore) {  
  92.         mIsAllowLoadMore = allowLoadMore;  
  93.     }  
  94.   
  95.     public boolean isAllowLoadMore() {  
  96.         return mIsAllowLoadMore;  
  97.     }  
  98.   
  99.     /** 
  100.      * 设置进度圈的颜色 
  101.      * @param colors 如:0xFFFF0000 
  102.      */  
  103.     public void setColorSchemeColors(int... colors){  
  104.         this.colors = colors;  
  105.     }  
  106.     /** 
  107.      * 设置进度圈的颜色 
  108.      * @param colorResIds 如:R.color.red 
  109.      */  
  110.     public void setColorSchemeResources(@ColorRes int... colorResIds) {  
  111.         final Resources res = getResources();  
  112.         int[] colorRes = new int[colorResIds.length];  
  113.         for (int i = 0; i < colorResIds.length; i++) {  
  114.             colorRes[i] = res.getColor(colorResIds[i]);  
  115.         }  
  116.         setColorSchemeColors(colorRes);  
  117.     }  
  118.   
  119.     @Override  
  120.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  121.         super.onLayout(changed, l, t, r, b);  
  122.   
  123.         if (!mIsFirst) {  
  124.   
  125.             createProgressView();  
  126.   
  127.             over:  
  128.             for (int i = 0; i < getChildCount(); i++) {  
  129.                 View childView = getChildAt(i);  
  130.                 if (childView instanceof SwipeRefreshLayout) {  
  131.                     ViewGroup viewGroup = (ViewGroup) childView;  
  132.                     for (int j = 0; j < viewGroup.getChildCount(); j++) {  
  133.                         View childViewJ = viewGroup.getChildAt(j);  
  134.                         if (childViewJ instanceof RecyclerView) {  
  135.                             mRecyclerView = (RecyclerView) childViewJ;  
  136.                             break over;  
  137.                         }  
  138.                     }  
  139.                 }  
  140.                 if(childView instanceof RecyclerView){  
  141.                     mRecyclerView = (RecyclerView) childView;  
  142.                     break over;  
  143.                 }  
  144.             }  
  145.             mIsFirst = true;  
  146.         }  
  147.     }  
  148.   
  149.   
  150.     @Override  
  151.     public boolean dispatchTouchEvent(MotionEvent event) {  
  152.   
  153.         if(!mIsAllowLoadMore) return super.dispatchTouchEvent(event);  
  154.   
  155.         switch (event.getAction()) {  
  156.             case MotionEvent.ACTION_DOWN:  
  157.                 mStartY = (int) event.getRawY();  
  158.                 break;  
  159.             case MotionEvent.ACTION_MOVE:  
  160.   
  161.                 if (!mStart) {  
  162.                     //如果不满足上拉的条件就直接分发事件  
  163.                     if(!canPullUp()){  
  164.                         return super.dispatchTouchEvent(event);  
  165.                     }  
  166.                     if (canPullUp() && !mIsCanScoll) {  
  167.                         showRefreshArrow();  
  168.                         mStartY = (int) event.getRawY();  
  169.                         mIsCanScoll = true;  
  170.                     } else {  
  171.                         //mStartY = (int) event.getRawY();  
  172.                         //hideRefreshArrow();  
  173.                         //hide();  
  174.                     }  
  175.                     if (mVisibleCanScoll) {  
  176.                         int endY = (int) event.getRawY();  
  177.                         int offset = mStartY - endY;  
  178.                         //System.out.println("----------------------offset:" + offset);  
  179.                         LayoutParams lp = (LayoutParams) mImageView.getLayoutParams();  
  180.                         int bottomMargin = lp.bottomMargin;  
  181.                         bottomMargin += offset;  
  182.                         if (bottomMargin >= PULL_IMAGE_SIZE_PX_MAX) {  
  183.                             bottomMargin = PULL_IMAGE_SIZE_PX_MAX;  
  184.                         }  
  185.   
  186.                         if (bottomMargin <= -PULL_IMAGE_SIZE_PX) {  
  187.                             bottomMargin = -PULL_IMAGE_SIZE_PX;  
  188.   
  189.                         }  
  190.                         lp.setMargins(lp.leftMargin, lp.topMargin, lp.rightMargin, bottomMargin);  
  191.                         mImageView.setLayoutParams(lp);  
  192.   
  193.                         rotateAniamtor(bottomMargin * ROTATE_ANIM_ANGLE_PER);  
  194.   
  195.                         mStartY = endY;  
  196.                     }  
  197.   
  198.                     LayoutParams lp = (LayoutParams) mImageView.getLayoutParams();  
  199.                     //如果按住上拉时,上拉箭头向下滑动的时候事件不应分发  
  200.                     if(mVisable && lp.bottomMargin > -PULL_IMAGE_SIZE_PX){  
  201.                         mIsDispatch = false;  
  202.                     }else if(mVisable && lp.bottomMargin == -PULL_IMAGE_SIZE_PX){//等到上拉箭头被隐藏掉的时候在分发事件  
  203.                         mIsDispatch = true;  
  204.                     }  
  205.   
  206.                     //是否分发事件  
  207.                     if(!mIsDispatch) {  
  208.                         return false;  
  209.                     }  
  210.                     else {  
  211.                         return super.dispatchTouchEvent(event);  
  212.                     }  
  213.                 }  
  214.                 break;  
  215.   
  216.             case MotionEvent.ACTION_UP:  
  217.             case MotionEvent.ACTION_CANCEL:  
  218.   
  219.                 if (!mStart) {  
  220.   
  221.                     if (mVisibleCanScoll) {  
  222.                         LayoutParams lp = (LayoutParams) mImageView.getLayoutParams();  
  223.                         if (lp.bottomMargin >= PULL_IMAGE_SIZE_PX_EXECUTE) {  
  224.                             //lp.setMargins(lp.leftMargin, lp.topMargin, lp.rightMargin, PULL_IMAGE_SIZE_PX / 3 * 2);  
  225.                             //mImageView.setLayoutParams(lp);  
  226.                             //start();  
  227.                             getValueToTranslation();  
  228.                             mPrepareAnimation = true;  
  229.   
  230.                             if (mOnPullListener != null) {  
  231.                                 mOnPullListener.onLoadMore(this);  
  232.                             }  
  233.                         } else {  
  234.   
  235.                             hideArrow();  
  236.   
  237.                         }  
  238.                     }  
  239.                     if (!mStart && !mPrepareAnimation)  
  240.                         hideArrow();  
  241.                 }  
  242.   
  243.                 mIsCanScoll = false;  
  244.   
  245.                 break;  
  246.         }  
  247.   
  248.         return super.dispatchTouchEvent(event);  
  249.     }  
  250.   
  251.     private void hideArrow() {  
  252.         LayoutParams lp = (LayoutParams) mImageView.getLayoutParams();  
  253.         //lp.setMargins(lp.leftMargin, lp.topMargin, lp.rightMargin, -PULL_IMAGE_SIZE_PX);  
  254.         //mImageView.setLayoutParams(lp);  
  255.   
  256.         translationTo(lp.bottomMargin,-PULL_IMAGE_SIZE_PX,false);  
  257.   
  258.     }  
  259.   
  260.     private void showRefreshArrow() {  
  261.         mImageView.setVisibility(View.VISIBLE);  
  262.   
  263.         visable();  
  264.     }  
  265.   
  266.     /** 
  267.      * 隐藏箭头显示的载体ImageView 
  268.      */  
  269.     private void hideRefreshArrow() {  
  270.         mImageView.setVisibility(View.GONE);  
  271.     }  
  272.   
  273.   
  274.     private boolean canPullUp() {  
  275.         if(mRecyclerView == null || mRecyclerView.getAdapter() == nullreturn false;  
  276.         RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager();  
  277.         mLastVisiblePosition = getLastVisibleItemPosition();  
  278.         int count = mRecyclerView.getAdapter().getItemCount();  
  279.         if (0 == count) {  
  280.             // 没有item的时候也可以上拉加载  
  281.             return true;  
  282.         } else if (mLastVisiblePosition == (count - 1)) {  
  283.             // 滑到底部了  
  284.             if (lm.findViewByPosition(count - 1).getBottom() <= getMeasuredHeight()) {  
  285.                 return true;  
  286.             }  
  287.         }  
  288.         return false;  
  289.     }  
  290.   
  291.   
  292.   
  293.     /** 
  294.      * 获取底部可见项的位置 
  295.      * 
  296.      * @return 
  297.      */  
  298.     private int getLastVisibleItemPosition() {  
  299.         RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager();  
  300.         int lastVisibleItemPosition = 0;  
  301.         if (lm instanceof GridLayoutManager) {  
  302.             lastVisibleItemPosition = ((GridLayoutManager) lm).findLastVisibleItemPosition();  
  303.         } else if (lm instanceof LinearLayoutManager) {  
  304.             lastVisibleItemPosition = ((LinearLayoutManager) lm).findLastVisibleItemPosition();  
  305.         }  
  306.         return lastVisibleItemPosition;  
  307.     }  
  308.   
  309.   
  310.     /** 
  311.      * 创建刷新View和初始化一些数据 
  312.      */  
  313.     private void createProgressView() {  
  314.         mImageView = new ImageView(getContext());  
  315.   
  316.         int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, PULL_IMAGE_SIZE, getContext().getResources().getDisplayMetrics());  
  317.         PULL_IMAGE_SIZE_PX = size;  
  318.         PULL_IMAGE_SIZE_PX_MAX = PULL_IMAGE_SIZE_PX * 2;  
  319.         PULL_IMAGE_SIZE_PX_EXECUTE = PULL_IMAGE_SIZE_PX;  
  320.         PULL_IMAGE_SIZE_PX_EXECUTE_REFRESH = PULL_IMAGE_SIZE_PX / 3 * 2;  
  321.         ROTATE_ANIM_ANGLE_PER = (360.0f / PULL_IMAGE_SIZE_PX_MAX);  
  322.         LayoutParams lp = new LayoutParams(size, size);  
  323.         lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);  
  324.         lp.addRule(RelativeLayout.CENTER_HORIZONTAL);  
  325.         lp.setMargins(lp.leftMargin, lp.topMargin, lp.rightMargin, -PULL_IMAGE_SIZE_PX);  
  326.         mImageView.setLayoutParams(lp);  
  327.         mImageView.setBackground(getShapeDrawable());  
  328.   
  329.         addView(mImageView);  
  330.         mImageView.setVisibility(View.GONE);  
  331.   
  332.         mProgress = new MaterialProgressDrawable(getContext(), mImageView);  
  333.   
  334.         mProgress.setBackgroundColor(CIRCLE_BG_LIGHT);  
  335.         //圈圈颜色,可以是多种颜色  
  336.         mProgress.setColorSchemeColors(colors);  
  337.         //设置圈圈的各种大小  
  338.         mProgress.updateSizes(MaterialProgressDrawable.LARGE);  
  339.   
  340.         mImageView.setImageDrawable(mProgress);  
  341.     }  
  342.   
  343.     /** 
  344.      * mImageView的背景 
  345.      */  
  346.     private Drawable getShapeDrawable() {  
  347.         /** 
  348.          * <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > 
  349.          <!-- 第一层  上部和左部偏移一定距离--> 
  350.          <item 
  351.          > 
  352.          <shape android:shape="oval"> 
  353.          <solid android:color="#f5f5f5" /> 
  354.          <!-- 描边 --> 
  355.          <stroke 
  356.          android:width="0.5dp" 
  357.          android:color="#99f5f5f5" /> 
  358.          </shape> 
  359.          </item> 
  360.          <!-- 第二层 下部和有部偏移一定距离--> 
  361.          <item 
  362.          android:left="2dp" 
  363.          android:top="2dp" 
  364.          android:bottom="2dp" 
  365.          android:right="2dp"> 
  366.          <shape android:shape="oval"> 
  367.          <solid android:color="#ffffff" /> 
  368.          <!-- 描边 --> 
  369.          <!--<stroke android:width="0.33dp" android:color="#dedede" />--> 
  370.          </shape> 
  371.          </item> 
  372.          </layer-list> 
  373.          */  
  374.         //代码实现  
  375.         GradientDrawable gradientDrawable = new GradientDrawable();  
  376.         gradientDrawable.setShape(GradientDrawable.OVAL);  
  377.         gradientDrawable.setColor(Color.parseColor("#f5f5f5"));  
  378.         int stroke = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0.5f, getContext().getResources().getDisplayMetrics());  
  379.         gradientDrawable.setStroke(stroke,Color.parseColor("#99f5f5f5"));  
  380.         GradientDrawable gradientDrawable2 = new GradientDrawable();  
  381.         gradientDrawable2.setShape(GradientDrawable.OVAL);  
  382.         gradientDrawable2.setColor(Color.parseColor("#ffffff"));  
  383.         LayerDrawable drawable = new LayerDrawable(new Drawable[]{gradientDrawable,gradientDrawable2});  
  384.         int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getContext().getResources().getDisplayMetrics());  
  385.         drawable.setLayerInset(1,padding,padding,padding,padding);////第一个参数1代表数组的第二个元素,为白色  
  386.         return drawable;  
  387.     }  
  388.   
  389.     /** 
  390.      * 隐藏箭头 
  391.      */  
  392.     private void hide() {  
  393.         if (mValueAnimator != null) {  
  394.             mValueAnimator.cancel();  
  395.             mVisable = false;  
  396.             mVisibleCanScoll = false;  
  397.         }  
  398.   
  399.     }  
  400.   
  401.     private void visable() {  
  402.         if (mValueAnimator == null) {  
  403.             mValueAnimator = mValueAnimator.ofFloat(0f, 1f);  
  404.             mValueAnimator.setDuration(10);  
  405.             mValueAnimator.setInterpolator(new DecelerateInterpolator());  
  406.             mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
  407.                 @Override  
  408.                 public void onAnimationUpdate(ValueAnimator animation) {  
  409.                     float n = (float) animation.getAnimatedValue();  
  410.                     //圈圈的旋转角度  
  411.                     mProgress.setProgressRotation(n * 0.5f);  
  412.                     //圈圈周长,0f-1F  
  413.                     mProgress.setStartEndTrim(0f, n * 0.8f);  
  414.                     //箭头大小,0f-1F  
  415.                     mProgress.setArrowScale(n);  
  416.                     //透明度,0-255  
  417.                     mProgress.setAlpha((int) (255 * n));  
  418.                 }  
  419.             });  
  420.             mValueAnimator.addListener(new AnimatorListenerAdapter() {  
  421.                 @Override  
  422.                 public void onAnimationEnd(Animator animation) {  
  423.                     super.onAnimationEnd(animation);  
  424.                     mVisable = true;  
  425.   
  426.                 }  
  427.             });  
  428.         }  
  429.   
  430.         if (!mValueAnimator.isRunning()) {  
  431.             if (!mVisable) {  
  432.                 //是否显示箭头  
  433.                 mProgress.showArrow(true);  
  434.                 mValueAnimator.start();  
  435.                 mVisibleCanScoll = true;  
  436.             }  
  437.         }  
  438.     }  
  439.   
  440.     private void start() {  
  441.         if (mVisable) {  
  442.             if (!mStart) {  
  443.                 mProgress.start();  
  444.   
  445.                 mStart = true;  
  446.   
  447.             }  
  448.         }  
  449.     }  
  450.   
  451.     /** 
  452.      * 计算执行动画的距离参数 
  453.      */  
  454.     private void getValueToTranslation() {  
  455.         //如果mImageView还没有被创建出来是不会执行的  
  456.         if(mImageView != null) {  
  457.             LayoutParams lp = (LayoutParams) mImageView.getLayoutParams();  
  458.             int bottomMargin = lp.bottomMargin;  
  459.             //执行平移  
  460.             translationTo(bottomMargin, PULL_IMAGE_SIZE_PX_EXECUTE_REFRESH, true);  
  461.         }  
  462.     }  
  463.   
  464.     private void stop() {  
  465.         if (mStart) {  
  466.             mProgress.stop();  
  467.             mStart = false;  
  468.             mVisable = false;  
  469.             mVisibleCanScoll = false;  
  470.         }  
  471.     }  
  472.   
  473.   
  474.     /** 
  475.      * 执行平移动画 
  476.      * @param from 
  477.      * @param to 
  478.      */  
  479.     private void translationTo(int from,int to,final boolean isShow){  
  480.         //1.调用ofInt(int...values)方法创建ValueAnimator对象  
  481.         ValueAnimator mAnimator = ValueAnimator.ofInt(from,to);  
  482.         //2.为目标对象的属性变化设置监听器  
  483.         mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
  484.   
  485.             @Override  
  486.             public void onAnimationUpdate(ValueAnimator animation) {  
  487.                 // 3.为目标对象的属性设置计算好的属性值  
  488.                 int animatorValue = (int)animation.getAnimatedValue();  
  489.                 MarginLayoutParams marginLayoutParams = (MarginLayoutParams) mImageView.getLayoutParams();  
  490.                 marginLayoutParams.bottomMargin = animatorValue;  
  491.                 mImageView.setLayoutParams(marginLayoutParams);  
  492.             }  
  493.         });  
  494.         mAnimator.addListener(new AnimatorListenerAdapter() {  
  495.             @Override  
  496.             public void onAnimationEnd(Animator animation) {  
  497.                 super.onAnimationEnd(animation);  
  498.                 if(isShow){  
  499.                     start();  
  500.                     mPrepareAnimation = false;  
  501.                 }else{  
  502.                     hideRefreshArrow();  
  503.                     hide();  
  504.                 }  
  505.   
  506.             }  
  507.         });  
  508.         //4.设置动画的持续时间、是否重复及重复次数等属性  
  509.         mAnimator.setDuration(100);  
  510.         //mAnimator.setRepeatCount(3);  
  511.         mAnimator.setRepeatMode(ValueAnimator.INFINITE);  
  512.         //5.为ValueAnimator设置目标对象并开始执行动画  
  513.         mAnimator.setTarget(mImageView);  
  514.         mAnimator.start();  
  515.     }  
  516.   
  517.     /** 
  518.      * 旋转动画效果 
  519.      */  
  520.     private void rotateAniamtor(float from){  
  521.   
  522.         ObjectAnimator mAnimatorRotate = ObjectAnimator.ofFloat(mImageView, "rotation",from,from + 1);  
  523.         mAnimatorRotate.setRepeatMode(Animation.INFINITE);  
  524.         mAnimatorRotate.setRepeatCount(1);  
  525.         mAnimatorRotate.setDuration(10);  
  526.         mAnimatorRotate.start();  
  527.     }  
  528.   
  529.   
  530.     /** 
  531.      * 加载更多或停止加载更多 
  532.      * @param refreshing 
  533.      */  
  534.     public void setRefreshing(boolean refreshing) {  
  535.         if(!mIsAllowLoadMore) return;  
  536.         if(refreshing){  
  537.             if(mStart) return;  
  538.             showRefreshArrow();  
  539.             getValueToTranslation();  
  540.             mPrepareAnimation = true;  
  541.   
  542.             if (mOnPullListener != null) {  
  543.                 mOnPullListener.onLoadMore(this);  
  544.             }  
  545.             mIsCanScoll = false;  
  546.         }else {  
  547.             stop();  
  548.             hideArrow();  
  549.         }  
  550.     }  
  551.   
  552.     /** 
  553.      * 当前是否在上拉刷新 
  554.      * @return 
  555.      */  
  556.     public boolean isRefreshing(){  
  557.         return mStart;  
  558.     }  
  559.   
  560.   
  561.     /** 
  562.      * 刷新加载回调接口 
  563.      * 
  564.      */  
  565.     public interface OnPullListener {  
  566.   
  567.         /** 
  568.          * 加载操作 
  569.          */  
  570.         void onLoadMore(PullRefreshLayout pullRefreshLayout);  
  571.     }  
  572.   
  573.     private OnPullListener mOnPullListener;  
  574.   
  575.     public void setOnPullListener(OnPullListener listener) {  
  576.         mOnPullListener = listener;  
  577.     }  
  578.   
  579. }  




好了,和下拉刷新的动画一样的效果终于实现了。


源码下载地址:CSDN下载地址

                        GitHub下载地址


参考:http://blog.csdn.net/zhongkejingwang/article/details/38868463

            http://blog.csdn.net/lmj623565791/article/details/51118836/

            http://blog.csdn.net/tyzlmjj/article/details/50557397

0 0
原创粉丝点击