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);
}
}