NestedScrollViewとRecyclerViewのネストされたダブルスライディングをサポートするレイアウトマネージャー

NestedScrollViewとRecyclerViewのネストされた使用の問題。インターネットで見たのは、RecyclerViewにsetNestedScrollingEnabled(false)を設定することです。ただし、このメソッドには問題があります。
つまり、RecyclerViewの高さをwrap_contentにする必要があります(そうしないと、高さが小さすぎて、下部のアイテムビューをスライドできません)、つまり、アイテムビューの数です。 、対応する高さが必要です。しかし、これは私が望んでいることではありません。まず、これにより、ViewHolderがリサイクルされなくなります。RecyclerViewはRecycleの意味を失います! 2つ目は、すばやく上にスライドすると、全体的なスライド効果に一貫性がなくなることです。この方法をエレガントと呼ぶ人もいますが、まったくエレガントではありません。

ビデオを見て、使用前後の効果を確認してください。

(オリジナルの作品、転載のソースを明記してくださいhttps//blog.csdn.net/hegan2010/article/details/113103751

この問題を解決するために、NestedScrollViewとRecyclerViewは、スライドの競合なしにダブルスライドでき、レイアウトマネージャーが作成されます。
原則は、RecyclerViewの表示領域の上部がNestedScrollViewの表示領域の上部よりも低い場合、Y軸上でRecyclerViewによって消費されるスライド距離を減らすか、0に設定するか、またはその差です。 NestedScrollViewがより多くのスライド距離を消費するように、2つの間の高さが異なります。

実装コードは次のとおりです(GridLayoutManagerから継承されます。これは、scrollVerticallyByメソッドがオーバーロードされている限り、実際の状況に応じてLayoutManagerが継承されるように変更できます)。

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import androidx.core.view.ScrollingView;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.lang.reflect.Field;

public class AutoScrollGridLayoutManager extends GridLayoutManager {
    
    
    public AutoScrollGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
    
    
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public AutoScrollGridLayoutManager(Context context, int spanCount) {
    
    
        super(context, spanCount);
    }

    public AutoScrollGridLayoutManager(Context context, int spanCount, int orientation,
            boolean reverseLayout) {
    
    
        super(context, spanCount, orientation, reverseLayout);
    }

    @Override
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
            RecyclerView.State state) {
    
    
        if (dy <= 0) {
    
    
            return super.scrollVerticallyBy(dy, recycler, state);
        }
        RecyclerView recyclerView = getRecyclerView();
        if (recyclerView == null) {
    
    
            return super.scrollVerticallyBy(dy, recycler, state);
        }
        ViewGroup parentView = getParentScrollingView(recyclerView);
        if (parentView == null) {
    
    
            return super.scrollVerticallyBy(dy, recycler, state);
        }
        Rect parentVisibleRect = new Rect();
        parentView.getGlobalVisibleRect(parentVisibleRect);
        Rect recyclerVisibleRect = new Rect();
        recyclerView.getGlobalVisibleRect(recyclerVisibleRect);
        int verticalOffset = recyclerVisibleRect.top - parentVisibleRect.top;
        if (verticalOffset <= 0) {
    
    
            return super.scrollVerticallyBy(dy, recycler, state);
        } else {
    
     // verticalOffset > 0
            if (dy <= verticalOffset) {
    
    
                return 0;
            } else {
    
     // dy > verticalOffset
                return super.scrollVerticallyBy(dy - verticalOffset, recycler, state);
            }
        }
    }

    public RecyclerView getRecyclerView() {
    
    
        try {
    
    
            Field field = RecyclerView.LayoutManager.class.getDeclaredField("mRecyclerView");
            field.setAccessible(true);
            return (RecyclerView) field.get(this);
        } catch (ReflectiveOperationException e) {
    
    
            return null;
        }
    }

    public static ViewGroup getParentScrollingView(View view) {
    
    
        do {
    
    
            ViewParent parent = view.getParent();
            if (parent == null || !(parent instanceof ViewGroup)) {
    
    
                return null;
            }
            ViewGroup parentView = (ViewGroup) parent;
            if (parentView instanceof ScrollingView) {
    
    
                return parentView;
            }
            view = parentView;
        } while (true);
    }
}

おすすめ

転載: blog.csdn.net/hegan2010/article/details/113103751