本文实例为大家分享了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实现下拉刷新和上拉加载所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)