国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android控件PullRefreshViewGroup實現(xiàn)下拉刷新和上拉加載

2019-12-12 03:27:32
字體:
來源:轉載
供稿:網友

本文實例為大家分享了Android實現(xiàn)下拉刷新和上拉加載更多的具體代碼,供大家參考,具體內容如下

先分享下源碼:Android實現(xiàn)下拉刷新和上拉加載更多

實現(xiàn)思路:由PullRefreshViewGroup控件來接管標準控件(比如RecyclerView、ListView等)的滑動,調用標準控件的內部方法進行短距離滑動,不再由標準控件自己來處理事件,而完全由PullRefreshViewGroup控件來處理觸摸事件。標準控件內部的滑動距離等屬性,通過反射獲得computeVerticalScrollExtent、computeVerticalScrollRange、computeVerticalScrollOffset這三個方法來獲得。

PullRefreshViewGroup控件的布局如下 

部分代碼實現(xiàn)

觸摸滑動事件處理

@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 函數(shù)的實現(xiàn)     // 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, 0, 0, -dy);      invalidate();     } else {      vTracker.computeCurrentVelocity(1000);       float yvel = vTracker.getYVelocity();      if (yvel != 0) {//為了滿足內部視圖的快速滾動( 中間內容視圖 )       mScroller.fling(0, 0, 0, (int) yvel, 0, 0, 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));//正數(shù)      distance = -(child0Top + mSrcHeightHead);//負數(shù)     }      //可以顯示加載更多嗎?     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;//負數(shù)      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);    }   }  } 

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 迁安市| 论坛| 平安县| 镶黄旗| 曲松县| 寿阳县| 绥化市| 积石山| 武城县| 新民市| 荣昌县| 哈巴河县| 临沧市| 通州区| 桃源县| 隆化县| 山东| 三台县| 高邑县| 策勒县| 土默特左旗| 乌兰察布市| 武清区| 汝城县| 琼中| 尉氏县| 遵义市| 岱山县| 于都县| 钟山县| 绍兴县| 襄城县| 八宿县| 新安县| 古蔺县| 竹山县| 库尔勒市| 恩平市| 永康市| 阜阳市| 罗平县|