赞
踩
解决方式:setNestedScrollingEnabled()方法
//启用嵌套滚动
mRecyclerView.setNestedScrollingEnabled(false);
public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild {
...
}
public interface NestedScrollingChild { /** * 设置嵌套滑动是否能用 * * @param enabled true to enable nested scrolling, false to disable */ public void setNestedScrollingEnabled(boolean enabled); /** * 判断嵌套滑动是否可用 * * @return true if nested scrolling is enabled */ public boolean isNestedScrollingEnabled(); /** * 开始嵌套滑动 * * @param axes 表示方向轴,有横向和竖向 */ public boolean startNestedScroll(int axes); /** * 停止嵌套滑动 */ public void stopNestedScroll(); /** * 判断是否有父View 支持嵌套滑动 * @return whether this view has a nested scrolling parent */ public boolean hasNestedScrollingParent(); /** * 在子View的onInterceptTouchEvent或者onTouch中,调用该方法通知父View滑动的距离 * * @param dx x轴上滑动的距离 * @param dy y轴上滑动的距离 * @param consumed 父view消费掉的scroll长度 * @param offsetInWindow 子View的窗体偏移量 * @return 支持的嵌套的父View 是否处理了 滑动事件 */ public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow); /** * 子view处理scroll后调用 * * @param dxConsumed x轴上被消费的距离(横向) * @param dyConsumed y轴上被消费的距离(竖向) * @param dxUnconsumed x轴上未被消费的距离 * @param dyUnconsumed y轴上未被消费的距离 * @param offsetInWindow 子View的窗体偏移量 * @return true if the event was dispatched, false if it could not be dispatched. */ public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow); /** * 滑行时调用 * * @param velocityX x 轴上的滑动速率 * @param velocityY y 轴上的滑动速率 * @param consumed 是否被消费 * @return true if the nested scrolling parent consumed or otherwise reacted to the fling */ public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed); /** * 进行滑行前调用 * * @param velocityX x 轴上的滑动速率 * @param velocityY y 轴上的滑动速率 * @return true if a nested scrolling parent consumed the fling */ public boolean dispatchNestedPreFling(float velocityX, float velocityY); } //RecyclerView解析 public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild { public RecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs, CLIP_TO_PADDING_ATTR, defStyle, 0); mClipToPadding = a.getBoolean(0, true); a.recycle(); } else { mClipToPadding = true; } setScrollContainer(true); //默认获取焦点 setFocusableInTouchMode(true); final ViewConfiguration vc = ViewConfiguration.get(context); mTouchSlop = vc.getScaledTouchSlop(); mMinFlingVelocity = vc.getScaledMinimumFlingVelocity(); mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); setWillNotDraw(getOverScrollMode() == View.OVER_SCROLL_NEVER); mItemAnimator.setListener(mItemAnimatorListener); initAdapterManager(); initChildrenHelper(); // If not explicitly specified this view is important for accessibility. if (ViewCompat.getImportantForAccessibility(this) == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) { ViewCompat.setImportantForAccessibility(this, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES); } mAccessibilityManager = (AccessibilityManager) getContext() .getSystemService(Context.ACCESSIBILITY_SERVICE); setAccessibilityDelegateCompat(new RecyclerViewAccessibilityDelegate(this)); // Create the layoutManager if specified. boolean nestedScrollingEnabled = true; if (attrs != null) { int defStyleRes = 0; TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RecyclerView, defStyle, defStyleRes); String layoutManagerName = a.getString(R.styleable.RecyclerView_layoutManager); int descendantFocusability = a.getInt( R.styleable.RecyclerView_android_descendantFocusability, -1); if (descendantFocusability == -1) { setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); } a.recycle(); createLayoutManager(context, layoutManagerName, attrs, defStyle, defStyleRes); if (Build.VERSION.SDK_INT >= 21) { a = context.obtainStyledAttributes(attrs, NESTED_SCROLLING_ATTRS, defStyle, defStyleRes); nestedScrollingEnabled = a.getBoolean(0, true); a.recycle(); } } else { setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); } //默认支持嵌套滚动 // Re-set whether nested scrolling is enabled so that it is set on all API levels setNestedScrollingEnabled(nestedScrollingEnabled); } @Override public void setNestedScrollingEnabled(boolean enabled) { getScrollingChildHelper().setNestedScrollingEnabled(enabled); } @Override public boolean isNestedScrollingEnabled() { return getScrollingChildHelper().isNestedScrollingEnabled(); } @Override public boolean startNestedScroll(int axes) { return getScrollingChildHelper().startNestedScroll(axes); } @Override public void stopNestedScroll() { getScrollingChildHelper().stopNestedScroll(); } @Override public boolean hasNestedScrollingParent() { return getScrollingChildHelper().hasNestedScrollingParent(); } @Override public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { return getScrollingChildHelper().dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); } @Override public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { return getScrollingChildHelper().dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); } @Override public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { return getScrollingChildHelper().dispatchNestedFling(velocityX, velocityY, consumed); } @Override public boolean dispatchNestedPreFling(float velocityX, float velocityY) { return getScrollingChildHelper().dispatchNestedPreFling(velocityX, velocityY); } 这是全部都交给getScrollingChildHelper()这个方法的返回对象处理了啊,看看这个方法是怎么实现的。 private NestedScrollingChildHelper getScrollingChildHelper() { if (mScrollingChildHelper == null) { mScrollingChildHelper = new NestedScrollingChildHelper(this); } return mScrollingChildHelper; }
public class NestedScrollingChildHelper { private final View mView; private ViewParent mNestedScrollingParent; private boolean mIsNestedScrollingEnabled; private int[] mTempNestedScrollConsumed; /** * Construct a new helper for a given view. */ public NestedScrollingChildHelper(View view) { mView = view; } /** * Enable nested scrolling. * * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass * method/{@link android.support.v4.view.NestedScrollingChild} interface method with the same * signature to implement the standard policy.</p> * * @param enabled true to enable nested scrolling dispatch from this view, false otherwise */ public void setNestedScrollingEnabled(boolean enabled) { if (mIsNestedScrollingEnabled) { ViewCompat.stopNestedScroll(mView); } mIsNestedScrollingEnabled = enabled; } /** * Check if nested scrolling is enabled for this view. * * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass * method/{@link android.support.v4.view.NestedScrollingChild} interface method with the same * signature to implement the standard policy.</p> * * @return true if nested scrolling is enabled for this view */ public boolean isNestedScrollingEnabled() { return mIsNestedScrollingEnabled; } . . . }
RecyclerView默认是setNestedScrollingEnabled(true),是支持嵌套滚动的,也就是说当它嵌套在NestedScrollView中时,默认会随着NestedScrollView滚动而滚动,放弃了自己的滚动
查看RecyclerView的源码发现,它会在构造方法中调用setFocusableInTouchMode(true),所以抢到焦点后一定会定位到第一行的位置突出RecyclerView的显示
解决方法就是NestScrollView节点添加
android:focusableInTouchMode="true"
在NestScrollView的子节点view添加:
android:descendantFocusability="blocksDescendants"
或者 直接mRecyclerVIew.setFocusableInTouchMode(false)
总结:
源码 :有些问题只能从源码里找出究竟 , 一点一点剖析才能看出问题的根本, 弄透一个接口的作用 , 那么有类似需求的时候,可以自定义控件实现该接口;再一个,就是在看的过程中, 我们会熟悉源码的风格,命令的方式和逻辑
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。