解決SwipeRefreshLayout與RecyclerView滑動衝突問題

背景:高版本的編譯環境中,SwipeRefreshLayout和RecyclerView並不存在滑動衝突問題,而我恰恰手裏有個target是22的項目,當我按照正常的邏輯寫完界面後,使用app發現滑動整個列表時兩個控件發生衝突,本着快速解決上線任務的原則,直接百度.
網上的完美解決方案如下

RecyclerView.OnScrollListener(){  
        @Override  
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {  
            int topRowVerticalPosition =  
                    (recyclerView == null || recyclerView.getChildCount() == 0) ?  0  : recyclerView.getChildAt(0).getTop();  
            swipeRefreshLayout.setEnabled(topRowVerticalPosition >= 0);  
        }  
  
        @Override  
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {  
            super.onScrollStateChanged(recyclerView, newState);  
        }  
    });  

使用完上面的代碼,依舊會出現bug:
從底部往回滑動時,如果當前頁面內可看見的第一個item剛好完整出現在界面上,這個時候繼續回滑,會出現觸發SwipeRefreshLayout的手勢 (該bug因爲操作難度的關係並不容易出現,但多操作幾次肯定會出現的)。

出現的原因:
是由於雖然recyclerView.getChildAt(0)取到的是第一個childView,但是由於RecyclerView自身的複用問題,第一個childView可能會被多次複用,如果僅僅判斷第一個childView的top是否大於等於0便會出現上述bug

解決方案:
如果firstChild處於列表的第一個位置,且top>=0,則下拉刷新控件可用

SwipeRefreshLayout layout) {
        rv.setOnScrollListener(new RecyclerView.OnScrollListener() {
            View firstChild;

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                if (recyclerView != null && recyclerView.getChildCount() > 0) {
                    firstChild = recyclerView.getChildAt(0);
                }
                int firstChildPosition = firstChild == null ? 0 : recyclerView.getChildLayoutPosition(firstChild);
                layout.setEnabled(firstChildPosition == 0 && firstChild.getTop()>=0);//如果firstChild處於列表的第一個位置,且top>=0,則下拉刷新控件可用
            }

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }
        });
    } 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章