1. 程式人生 > >Android滑動衝突解決方式(下拉重新整理上拉載入更多,適配RecyclerView/ListView/ScrollView)

Android滑動衝突解決方式(下拉重新整理上拉載入更多,適配RecyclerView/ListView/ScrollView)

    @Override
    public boolean judgeIntercept(float curInterceptY, float lastInterceptY, boolean isHeaderShow, boolean isFooterShow, boolean allowLoadMore) {
         boolean intercept;

         int firstVisiblePos = layoutManager.findFirstVisibleItemPosition();
         View firstView = rv.getChildAt(firstVisiblePos);
         if (firstVisiblePos == 0 && firstView.getTop() == 0) {
             intercept = curInterceptY > lastInterceptY || isHeaderShow;
         } else {
             if (allowLoadMore && layoutManager.findLastVisibleItemPosition() == layoutManager.getItemCount() - 1) {
                 intercept = curInterceptY < lastInterceptY || isFooterShow;
             } else {
                 intercept = false;
             }
         }

         return intercept;
    }
1.MotionEvent.ACTION_DOWN中,必須返回false,不攔截,一旦攔截,後續的ACTION_MOVE和ACTION_UP將直接交由FrameLayout的onTouchEvent(ev)處理

 2.MotionEvent.ACTION_UP中也必須返回false,因為一組事件以ACTION_UP結尾,則ACTION_UP這個事件必定會經過FrameLayout.onTouchEvent(ev),如果攔截了,則子View針對ACTION_UP需要處理的事情就無法完成。

 3.MotionEvent.ACTION_MOVE中根據實際情況判斷是否攔截。

    private float moveDis;

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (touchHelper != null) {
            float curTouchY = ev.getY();
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    break;
                case MotionEvent.ACTION_MOVE:
                    moveDis = curTouchY - lastInterceptY;
                    if (Math.abs(moveDis) < touchSlop) {
                        break;
                    }
                    if (isRefreshing || isLoadMore) {
                        break;
                    }
                    moveDis = moveDis * kMoveFactor;

                    if (touchHelper.isContentSlideToTop()) {
                        updateHeaderMargin(moveDis);
                    } else if (touchHelper.isContentSlideToBottom()) {
                        updateFooterMargin(moveDis);
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (moveDis > 0) {
                        if (touchHelper.isContentSlideToTop()) {
                            if (headerParams.topMargin < 0) {
                                scrollHeaderByAnimator(headerParams.topMargin, -headerHeight);
                                if (header != null) {
                                    header.onPullToRefresh(moveDis);
                                }
                            } else {
                                scrollHeaderByAnimator(headerParams.topMargin, 0);
                                if (header != null) {
                                    header.onRefreshing();
                                }
                                isRefreshing = true;
                                if (listener != null) {
                                    listener.onRefresh();
                                }
                            }
                        }
                    } else {
                        if (touchHelper.isContentSlideToBottom()) {
                            if (footerParams.topMargin > height - footerHeight) {
                                scrollFooterByAnimator(false, footerParams.topMargin, height);
                                if (footer != null) {
                                    footer.onPullToLoadMore(moveDis);
                                }
                            } else {
                                scrollFooterByAnimator(false, footerParams.topMargin, height - footerHeight);
                                if (footer != null) {
                                    footer.onLoadMore();
                                }
                                isLoadMore = true;
                                if (listener != null) {
                                    listener.onLoadMore();
                                }
                            }
                        }
                    }
                    break;
            }
        }
        return true;
    }
private void updateHeaderMargin(float moveDis) {
        moveDis = moveDis < 0 ? 0 : moveDis;
        headerParams.topMargin = (int) (-headerHeight + moveDis);
        headerVG.setLayoutParams(headerParams);

        setChildViewTopMargin((int) moveDis);

        if (header != null) {
            if (moveDis < headerHeight) {
                header.onPullToRefresh(moveDis);
            } else {
                header.onReleaseToRefresh(moveDis);
            }
        }
    }

    private void setChildViewTopMargin(int topMargin) {
        LayoutParams childParams = (LayoutParams) childView.getLayoutParams();
        childParams.topMargin = topMargin;
        childView.setLayoutParams(childParams);
    }

    private void updateFooterMargin(float moveDis) {
        moveDis = moveDis > 0 ? 0 : moveDis;
        footerParams.topMargin = (int) (height + moveDis);
        footerVG.setLayoutParams(footerParams);

        setChildViewBottomMargin((int) Math.abs(moveDis));
        scrollContentToBottom((int) -moveDis);

        if (footer != null) {
            if (Math.abs(moveDis) < footerHeight) {
                footer.onPullToLoadMore(moveDis);
            } else {
                footer.onReleaseToLoadMore(moveDis);
            }
        }
    }

    private void setChildViewBottomMargin(int bottomMargin) {
        LayoutParams childParams = (LayoutParams) childView.getLayoutParams();
        childParams.bottomMargin = bottomMargin;
        childView.setLayoutParams(childParams);
    }

    private void scrollContentToBottom(int deltaY) {
        if (childView instanceof RecyclerView) {
            childView.scrollBy(0, deltaY);
        } else if (childView instanceof ListView) {
            ((ListView) childView).smoothScrollBy(deltaY, 0);
        } else if (childView instanceof ScrollView) {
            childView.scrollBy(0, deltaY);
        }
    }

    private void scrollHeaderByAnimator(float startY, float endY) {
        ValueAnimator animator = ValueAnimator.ofFloat(startY, endY);
        animator.setDuration(kDuration);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float floatValue = (float) animation.getAnimatedValue();
                headerParams.topMargin = (int) floatValue;
                headerVG.setLayoutParams(headerParams);

                setChildViewTopMargin((int) (headerHeight + floatValue));
            }
        });
        animator.start();
    }

    private void scrollFooterByAnimator(final boolean isAuto, float startY, float endY) {
        ValueAnimator animator = ValueAnimator.ofFloat(startY, endY);
        animator.setDuration(kDuration);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float floatValue = (float) animation.getAnimatedValue();
                footerParams.topMargin = (int) floatValue;
                footerVG.setLayoutParams(footerParams);

                int bottomMargin = (int) (height - floatValue);
                setChildViewBottomMargin(bottomMargin);
                if (isAuto) {
                    scrollContentToBottom(bottomMargin);
                    if (footer != null) {
                        footer.onPullToLoadMore(bottomMargin);
                        if (bottomMargin == footerHeight) {
                            footer.onLoadMore();
                        }
                    }
                }
            }
        });
        animator.start();
    }
原始碼下載:點選開啟連結

不完善點還待指正!!!



相關推薦

Android滑動衝突解決方式(重新整理載入,RecyclerView/ListView/ScrollView)

@Override public boolean judgeIntercept(float curInterceptY, float lastInterceptY, boolean isHeaderShow, boolean isFooterShow, boolean allowLoadM

基於better-scroll的重新整理載入

目錄 前言 專案中使用的截圖如下 封裝better-scroll 元件的使用 前言 本來想使用vux的scroller元件,但是看到官方說不在維護了,而且在提供的樣例裡面,雖然例子有可以自定義載入等待區域以及文字提示的內容,但是實際上卻沒有找到相關樣例程式碼,改來改去也改

IOS控制元件系列二---優雅的UITableView的MVC模式設計,支援自定義重新整理/載入檢視(含swift)

demo效果如下: 本小框架設計原則依舊按照之前的慣例: 1.擴充套件性好,程式碼不冗餘(整個重新整理的頭部與底部程式碼不超過300行)。 2.邏輯清晰。 3.回撥介面清晰。 4.移植性好。 對於擴充套件性本框架擴充套件點如下: 1.框架中的

CoordinatorLayout AppBarLayout 結合重新整理 載入滑動衝突解決

如果appBarLayout中有摺疊控制元件 CollapsingToolbarLayout 或者其他一些控制元件 在滾動的時候進行判斷和重新整理事件處理 在這裡:重新整理框架:為 SwipyRefreshLayout 第一步:設定appBarLayout的監聽: if

android重新整理,載入

public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerview; private ArrayList<Integer> mList = new ArrayL

Android打造 ListView GridView等 通用的重新整理 自動載入的元件

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

重新整理載入框架:android-Ultra-Pull-To-Refresh

下拉重新整理上拉載入框架:PtrClassicFrameLayout 1、一個優雅的框架實現下拉重新整理上拉載入,學習來源:點選開啟連結 2、如何使用: 2.1、在專案中引入: compile 'com.shizhefei:MVCHelper-UltraRefresh:1

AndroidListView重新整理載入效果實現

  在Android開發中,下拉重新整理和上拉載入更多在很多app中都會有用到,下面就是具體的實現的方法。 首先,我們自定義一個RefreshListView來繼承與ListView,下面是程式碼: package com.example.downrefresh; import

Android 列表重新整理載入分頁功能

手機app 列表頁很常用,當資料特別多的時候,為了更好地使用者體驗,需要進行分頁處理。那麼分頁功能怎麼做呢? 看如下核心程式碼 if (mPage == 1 && mList != null) { mList.clear();

Android 重新整理載入PullToRefresh

PullToRefresh 開發者可以使用 PullToRefresh 對各種控制元件實現下拉重新整理或者上拉載入以及可以自定義重新整理和載入部分的檢視。 目前支援:ScrollView,ListView,WebView,RecyclerView。 PullToRefresh的使用步驟

Android滑動衝突解決方法

敘述 滑動衝突可以說是日常開發中比較常見的一類問題,也是比較讓人頭疼的一類問題,尤其是在使用第三方框架的時候,兩個原本完美的控制元件,組合在一起之後,忽然發現整個世界都不好了。 關於滑動衝突 滑動衝突分類### 滑動衝突,總的來說就是兩類。 同方向滑動衝突 比

自個兒寫Android重新整理/載入控制元件

前段時間自己寫了一個能夠“通用”的,支援下拉重新整理和上拉載入的自定義控制元件。可能現如今這已經不新鮮了,但有興趣的朋友還是可以一起來看看的。 與通常的View配合使用(比如ImageView) 與ListView配合使用 與Recycl

Android ListView 實現重新整理載入

1.簡介        無疑,在Android開發中,ListView是使用非常頻繁的控制元件之一,ListView提供一個列表的容易,允許我們以列表的形式將資料展示到介面上,但是Google給我們提供的原生ListView的控制元件,雖然在功能上很強大,但是在使用

Android ListView重新整理載入

把這兩天的心得記錄下來,以後用到不會忘。 先說下拉重新整理,下拉重新整理我們主要用到了android自帶v4jar包中的一個控制元件SwipeRefreshLayout,如果下面是xml檔案, 如果你在寫報錯的話,換一個最新的v4包就可以了。 <android

android 打造真正的重新整理載入recyclerview(三):重新整理載入

前言 在開發過程中,我想了兩種方案。一是使用LinearLayout巢狀頭部、recyclerview、尾部的方式,如下圖: 當recyclerview滑動到頂部時,移動LinearLayout露出頭部; 當recyclerview滑動到底

Android scrollview中巢狀listview實現listview重新整理載入

我們都知道在Android中scrollview和listview都能滑動,如果scrollview巢狀listview會出現一些問題,比如listview不能正常顯示item...但是在一些專案中,一些頁面內容比較多,需要在外面放一個scrollview,裡面還會巢狀li

android 打造真正的重新整理載入recyclerview(一):使用

版本更新資訊 –V1.1.1 修復: PullToLoadRecyclerView中EmptyView失效的問題; 當使用ViewPager時,會出現觸控事件衝突; 優化: 當items不能填滿RecyclerView時,將隱藏載入底部; Pu

快速整合Android實現重新整理載入

本文實現一分鐘快速整合BGARefreshLayout下拉重新整理和上拉載入的功能. 這個是簡單單功能的整合方法,詳細BGARefreshLayout請到github中的demo,這只是我簡化版快速整合. 重要的程式碼實現如下: MainActivity類: pub

android-----滑動衝突解決案例

        之前的幾篇部落格,我測試了View事件分發機制中的一些知識點,我們理解事件分發機制的目的就是為了能夠更好了知道View中事件的傳遞過程進而能夠對於滑動衝突有針對性的解決措施,今天我們通過一個翻頁例項來學習下滑動處理的方式之一-----外部攔截法;      

Android自定義控制元件實戰——實現仿IOS重新整理載入 PullToRefreshLayout

         下拉重新整理控制元件,網上有很多版本,有自定義Layout佈局的,也有封裝控制元件的,各種實現方式的都有。但是很少有人告訴你具體如何實現的,今天我們就來一步步實現自己封裝的 PullToRefreshLayout 完美的解決下拉重新整理,上拉載入問題。