高仿京東下拉刷新,輕松上手!

直接進入主題,先來看一下京東的實現效果:
jd.gif
以及我自己的實現效果:
myjd.gif

實現過程

1.下拉原理
layout.png

整個布局為繼承自LinearLayout的Viewgroup,分為頭部及下面的列表部分,通過設置HeaderView的topMargin屬性為負使HeaderView向屏幕上方偏移。
初始化時設置HeaderView的topMargin為負的HeaderView的高度可以將HeaderView完全隱藏,從而屏幕中只看得到列表部分。下拉過程中根據手指劃過的距離不斷更新HeaderView的topMargin值來改變HeaderView的可視范圍從而達到下拉的效果。

2.效果實現

觀察京東客戶端的下拉過程,可以看出下拉過程中快遞員和包裹是不斷放大的并且透明度在增加,當HeaderView完全可見時達到最大值并且快遞員“取到”包裹,松開手后快遞員開始“拼命送貨”。

其中放大效果我是用ScaleDrawable實現,通過手指劃過的位移改變Drawable的level從而改變圖片的大小,不熟悉ScaleDrawable的可以參考Android Drawable之ScaleDrawable。松開手后快遞員奔跑是由幀動畫實現。

3.關鍵代碼

攔截部分:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {    
    switch (event.getAction()) {        
        case MotionEvent.ACTION_DOWN:           
             mTouchY = event.getY();
             break; 
        case MotionEvent.ACTION_MOVE:
             float dy = event.getY() - mTouchY; 
            //當RecyclerView移到頂部并且手指向下滑動時,攔截事件,由自己處理Touch事件           
             if (dy > 0 && canPull)              
                  return true;       
        case MotionEvent.ACTION_UP:  
        default:            
             break;    
    }    
    return false;
}

滑動部分:

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:
            float dy = event.getY() - mTouchY;
            mTouchY = event.getY();
            if (Math.abs(mTouchY)<touchSlop)
                break;
            if (mCurrentStatus != STATUS_REFRESHING) {
                //除以2是增加下拉的阻力感
                headerLayoutParams.topMargin += dy / 2;
                //此時為向上滑動到頭部完全隱藏的情況,繼續滑動的話應該交由RecyclerView處理了,故返回false自己不消耗事件。
                if (headerLayoutParams.topMargin<=hideHeaderHeight){
                    headerLayoutParams.topMargin=hideHeaderHeight;
                    mHeaderView.requestLayout();
                    return false;
                }
                //此時為頭部完全顯示的情況
                if (headerLayoutParams.topMargin>=0){
                    mCurrentStatus = STATUS_RELEASE_TO_REFRESH;
                }else {
                    mCurrentStatus = STATUS_PULL_TO_REFRESH;
                    //改變圖片的大小及透明度
                    onLevelChanged((hideHeaderHeight-headerLayoutParams.topMargin)*100/hideHeaderHeight);
                }
                mHeaderView.requestLayout();
            }
            break;
        case MotionEvent.ACTION_UP:
        if (mCurrentStatus == STATUS_PULL_TO_REFRESH){
            //屬性動畫實現平滑滾動
           headerAnimation(headerLayoutParams.topMargin,hideHeaderHeight,350,null);
        }else if (mCurrentStatus == STATUS_RELEASE_TO_REFRESH){
            mCurrentStatus = STATUS_REFRESHING;
            headerAnimation(headerLayoutParams.topMargin,0,250,null);
            if (listener!=null)
                listener.onRefresh();
        }
        break;
    }
    updateHeaderView();
    lastStatus = mCurrentStatus;
    return super.onTouchEvent(event);
}

<br />

具體代碼可以參考https://github.com/tangr2015/JDPullToRefresh

<br />
<br />

參考Android下拉刷新完全解析,教你如何一分鐘實現下拉刷新功能

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,333評論 25 708
  • 博文出處:帶你實現仿美團的下拉刷新,歡迎大家關注我的博客,謝謝! 有一段時間沒更新博客了,近來都在做畢業設計,今天...
    俞其榮閱讀 3,289評論 1 32
  • 自定義view之自定義下拉刷新控件 經過了之前的學習,這一次擼一個能用的:在很多app中都有下拉刷新的功能,所以這...
    Ugly_K閱讀 2,156評論 1 15
  • 買了幾套16開的線裝豎版,發現太好讀了。這不就象七肢通的語言表達一樣嗎,不同的語言結構應該用不同的載體: 同步并發...
    掌門_艾老師閱讀 208評論 0 0
  • 每個孩子都有自然向上、向善的能力。 以下來自一位初三男生的故事…… 第一幕: 這像一個衛生間 ————發泄.安全...
    福州生命港灣閱讀 664評論 1 1