Android控件PullRefreshViewGroup实现下拉刷新和上拉加载

Android控件PullRefreshViewGroup实现下拉刷新和上拉加载,第1张

概述本文实例为大家分享了Android实现下拉刷新和上拉加载更多的具体代码,供大家参考,具体内容如下

本文实例为大家分享了AndroID实现下拉刷新和上拉加载更多的具体代码,供大家参考,具体内容如下

先分享下源码:AndroID实现下拉刷新和上拉加载更多

实现思路:由PullRefreshVIEwGroup控件来接管标准控件(比如RecyclerVIEw、ListVIEw等)的滑动,调用标准控件的内部方法进行短距离滑动,不再由标准控件自己来处理事件,而完全由PullRefreshVIEwGroup控件来处理触摸事件。标准控件内部的滑动距离等属性,通过反射获得computeVerticalScrollExtent、computeVerticalScrollRange、computeVerticalScrollOffset这三个方法来获得。

PullRefreshVIEwGroup控件的布局如下 

部分代码实现

触摸滑动事件处理

@OverrIDe  public boolean onIntercepttouchEvent(MotionEvent ev) {   boolean bret = false;   switch (ev.getAction()) {    case MotionEvent.ACTION_DOWN: {     mPreY = ev.getY();     Log.d(TAG,"mPreY:" + String.valueOf(mPreY));    }    break;    case MotionEvent.ACTION_MOVE: {     float curY = ev.getY();     float distance = curY - mPreY;     if (Math.abs(distance) >= mtouchSlop) {      mSlIDing = bret = true;       //修正第一次滑动的卡顿      if (distance > 0) {       mPreY += mtouchSlop;      } else {       mPreY -= mtouchSlop;      }       if (!mScroller.isFinished()) {       mScroller.abortAnimation();      }     } else {      mSlIDing = bret = false;     }    }    break;    case MotionEvent.ACTION_UP:    case MotionEvent.ACTION_CANCEL: {     bret = mSlIDing;    }    break;   }   return bret ? true : super.onIntercepttouchEvent(ev);  }   @OverrIDe  public boolean ontouchEvent(MotionEvent event) {   boolean bret = false;    vTracker.addMovement(event);    switch (event.getAction()) {    case MotionEvent.ACTION_DOWN: {     mPreY = event.getY();     bret = true;    }    break;    case MotionEvent.ACTION_MOVE: {     float curY = event.getY();     float distance = curY - mPreY;     Log.d(TAG,"mPreY:" + String.valueOf(mPreY) + " distance:" + String.valueOf(distance));     if (distance != 0) {      bret = true;       if (mSrcHeighthead == -1 && mHasPullRefresh) {       VIEw child0VIEw = mheadVIEw;       mSrcHeighthead = child0VIEw.getHeight();      }       scrollBy(distance);     }      mPreY = curY;    }    break;    case MotionEvent.ACTION_UP:    case MotionEvent.ACTION_CANCEL: {     mPreCurY = 0;      VIEw child0VIEw = mheadVIEw;     int child0Height = null != child0VIEw ? child0VIEw.getHeight() : 0;     int child0Height2 = null != child0VIEw ? child0VIEw.getLayoutParams().height : 0; //视图的最终高度是有这个来决定的,请看onMeasure 函数的实现     // int child0Height3 = child0VIEw.getMeasuredHeight();     if (child0Height2 != child0Height) {      child0Height = child0Height2;     }     int child0top = null != child0VIEw ? child0VIEw.gettop() : 0;     int dy = child0Height - mSrcHeighthead + (mSrcHeighthead - Math.abs(child0top));     Log.d(TAG,"ontouchEvent()ACTION_UP child0Height:" + String.valueOf(child0Height) + " mSrcHeighthead:" + String.valueOf(mSrcHeighthead) + " child0top:" + String.valueOf(child0top));     if (dy > 0) {//恢复拉伸视图的位置      if (!mloadingMore && dy > mCanRefreshHeight && child0top + child0Height2 > mCanRefreshHeight && mRefreshLoad != null) {       dy -= mCanRefreshHeight;        if (!mpullRefreshLoading) {        mpullRefreshLoading = true;        mTvRefreshInfo.setText("正在加载...");        mRefreshLoad.pullRefreshStartLoad();       }      }      mScroller.startScroll(0,-dy);      invalIDate();     } else {      vTracker.computeCurrentVeLocity(1000);       float yvel = vTracker.getYVeLocity();      if (yvel != 0) {//为了满足内部视图的快速滚动( 中间内容视图 )       mScroller.fling(0,(int) yvel,Integer.MIN_VALUE,Integer.MAX_VALUE);       invalIDate();      }     }      vTracker.clear();     bret = true;    }    break;   }   return bret ? true : super.ontouchEvent(event);  } 

小距离滑动代码

private voID scrollBy(float distance) {   VIEw child0VIEw = mheadVIEw;   VIEw child1VIEw = getChildAt(null == mheadVIEw ? 0 : 1);   float distanceRemain = 0;    int child0top = null != child0VIEw ? child0VIEw.gettop() : 0;   // int child0Height = child0VIEw.getHeight();    if (distance < 0) {//向上    int child1top = child1VIEw.gettop();    // int child1Height = child1VIEw.getHeight();     //child0VIEw 缩小    if (-1 != mSrcHeighthead && null != child0VIEw && child0VIEw.getHeight() > mSrcHeighthead) {     float off = distance;     if (child0VIEw.getHeight() + distance < mSrcHeighthead) {      off = -(child0VIEw.getHeight() - mSrcHeighthead);      distance -= off;     } else {      distance = 0;     }      child0VIEw.getLayoutParams().height += (int) off;     child1top += (int) off; //child0vIEw 缩小的同时,child1vIEw 的高度也会随之上升 这里很重要     requestLayout();     child1VIEw.offsettopAndBottom((int) off);     if (null != mTailVIEw) {      mTailVIEw.offsettopAndBottom((int) off);     }    }     if (distance != 0) {     if (child0top + mSrcHeighthead + distance <= 0) {      distanceRemain = -(distance + (child0top + mSrcHeighthead));//正数      distance = -(child0top + mSrcHeighthead);//负数     }      //可以显示加载更多吗?     boolean bDirectDown = false;     boolean bCanScroll = child1VIEw.canScrollVertically(1) || child1VIEw.canScrollVertically(-1);     if (!bCanScroll) {      int child1ChildCount = 0;      if (child1VIEw instanceof VIEwGroup) {       child1ChildCount = ((VIEwGroup) child1VIEw).getChildCount();      }      if (child1ChildCount > 0) {       VIEwGroup vIEwGroupChild1 = (VIEwGroup) child1VIEw;        VIEw child1LastItem = vIEwGroupChild1.getChildAt(child1ChildCount - 1);       int child1VIEwBottom = vIEwGroupChild1.getBottom();       int child1LastItemBottom = child1LastItem.getBottom() + child1top; //相对于 ImageScaleVIEwGroup 的位置       //增加 child1VIEwBottom > getHeight() 来控制 ScrollVIEw       if (child1LastItemBottom == getHeight()) {        bDirectDown = true;       }      }     }     //正在下拉刷新的时候,不能显示加载更多     if ((bCanScroll || bDirectDown) && null != mTailVIEw && !mpullRefreshLoading) {       int nVerticalScrollExtent = 0,nVerticalScrollRange = 0,nVerticalScrollOffset = 0;      Class c = null;       try {       c = Class.forname(child1VIEw.getClass().getname());      } catch (Exception ex) {       }      try {       if (null == mComputeVerticalScrollExtent) {        Method computeVerticalScrollExtent = findcomputeVerticalMethod(c,"computeVerticalScrollExtent");        computeVerticalScrollExtent.setAccessible(true);        mComputeVerticalScrollExtent = computeVerticalScrollExtent;       }       nVerticalScrollExtent = (int) mComputeVerticalScrollExtent.invoke(child1VIEw);      } catch (Exception ex) {       }      try {       if (null == mComputeVerticalScrollRange) {        Method computeVerticalScrollRange = findcomputeVerticalMethod(c,"computeVerticalScrollRange");        computeVerticalScrollRange.setAccessible(true);        mComputeVerticalScrollRange = computeVerticalScrollRange;       }        nVerticalScrollRange = (int) mComputeVerticalScrollRange.invoke(child1VIEw);      } catch (Exception ex) {       }      try {       if (null == mComputeVerticalScrollOffset) {        Method computeVerticalScrollOffset = findcomputeVerticalMethod(c,"computeVerticalScrollOffset");        computeVerticalScrollOffset.setAccessible(true);        mComputeVerticalScrollOffset = computeVerticalScrollOffset;       }       nVerticalScrollOffset = (int) mComputeVerticalScrollOffset.invoke(child1VIEw);      } catch (Exception ex) {       }        int range = nVerticalScrollRange - nVerticalScrollExtent;      if (nVerticalScrollOffset + distanceRemain > range) {       float nOff = distanceRemain - (range - nVerticalScrollOffset);        distanceRemain = range - nVerticalScrollOffset;       distance -= nOff;      }       int child3Bottom = mTailVIEw.getBottom();       if (child3Bottom + distance < getHeight()) {       distance = getHeight() - child3Bottom;      }     }      if (!bCanScroll) {      distanceRemain = 0;     }    }    } else {//向下    int nScrollOffset = 0;    try {     Class c = Class.forname(child1VIEw.getClass().getname());     Method computeVerticalScrollOffset = findcomputeVerticalMethod(c,"computeVerticalScrollOffset");//c.getDeclaredMethod("computeVerticalScrollOffset");     computeVerticalScrollOffset.setAccessible(true);     nScrollOffset = (int) computeVerticalScrollOffset.invoke(child1VIEw);    } catch (Exception ex) {     }     int child2top = null != mTailVIEw ? mTailVIEw.gettop() : getHeight();//注意默认值    if (child2top < getHeight()) {     if (child2top + distance > getHeight()) {      distanceRemain = distance - (getHeight() - child2top);      distance = getHeight() - child2top;     }    } else if (nScrollOffset > 0) {//内部有滚动,那么就要计算内部滚动距离,其他分配给整体滚动     if (nScrollOffset - distance <= 0) {      distanceRemain = -nScrollOffset;      // distance = distance - nScrollOffset;      distance = 0; //内部能滚动,不让外部去滚动      if (!mScroller.isFinished()) {       mScroller.abortAnimation(); //内部滚动完后,立即停止      }     } else {      distanceRemain = -distance;//负数      distance = 0;     }    } else {     if (child0top + distance > 0) {//child0放大,child1移动      int off = (int) (child0top + distance);      distance = -child0top;       if (null != child0VIEw) {       child0VIEw.getLayoutParams().height += off;       requestLayout();      } else {       off = 0;      }       child1VIEw.offsettopAndBottom(off);      if (null != mTailVIEw) {       mTailVIEw.offsettopAndBottom(off);      }     }    }   }    if (0 != (int) distance) {    if (null != child0VIEw) {     child0VIEw.offsettopAndBottom((int) distance);    }    child1VIEw.offsettopAndBottom((int) distance);    if (null != mTailVIEw) {     mTailVIEw.offsettopAndBottom((int) distance);    }     requestLayout();//奇酷360这里必须调用,否则显示有点问题   }    scrollByForMIDVIEw(distanceRemain);//外部无法滚动的时候,内部滚动    if (!mpullRefreshLoading && !mloadingMore) {    int tailvIEwtop = null != mTailVIEw ? mTailVIEw.gettop() : getHeight();//注意默认值     if (tailvIEwtop < getHeight() && mHasLoadMore) {//加载更多     mloadingMore = true;     if (mRefreshLoad != null) {      mRefreshLoad.pullUpStartLoadMore();     }    } else {     if (mHasPullRefresh) {      if (distance < 0) {       int child0Bottom = child0VIEw.getBottom();       if (child0Bottom < mCanRefreshHeight) {        mTvRefreshInfo.setText("下拉刷新");       }      } else {       int child0Bottom = child0VIEw.getBottom();       if (child0Bottom > mCanRefreshHeight) {        mTvRefreshInfo.setText("松开刷新");       }      }     }    }   }  } 

处理标准控件小距离滚动代码,这里ListVIEw有点特殊。

private voID scrollByForMIDVIEw(float distanceRemain) {   if (0 != (int) distanceRemain) {    VIEw child1VIEw = getChildAt(null == mheadVIEw ? 0 : 1);    if (child1VIEw instanceof ListVIEw) {     ((ListVIEw) child1VIEw).smoothScrollBy((int) distanceRemain,0);    } /*else if (child1VIEw instanceof ScrollVIEw){     ((ScrollVIEw) child1VIEw).smoothScrollBy(0,(int) distanceRemain);    }*/ else {     child1VIEw.scrollBy(0,(int) distanceRemain);    }   }  } 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android控件PullRefreshViewGroup实现下拉刷新和上拉加载全部内容,希望文章能够帮你解决Android控件PullRefreshViewGroup实现下拉刷新和上拉加载所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1146737.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存