Ответ 1
EDIT: для этой ошибки существует билет. Вы могли бы определенно сделать то, что artur.dr... @gmail.com сделал и расширил RecyclerView, чтобы переопределить RecyclerView # dispatchNestedScroll, чтобы всегда возвращать false (он пишет правду в своем отчете), вы можете работать с анимацией overscroll, хотя я уверен, что это может сломать что-то по линии.
К сожалению, как кодируется RecyclerView и как создается NestedScrollingChild API, нет чистого способа добиться желаемого поведения.
Это из RecyclerView (23.1.1, однако я не верю никакой версии, прежде чем она исправляет проблему) внутри метода scrollByInternal.
if (dispatchNestedScroll(consumedX, consumedY, unconsumedX, unconsumedY, mScrollOffset)) {
// Update the last touch co-ords, taking any scroll offset into account
mLastTouchX -= mScrollOffset[0];
mLastTouchY -= mScrollOffset[1];
if (ev != null) {
ev.offsetLocation(mScrollOffset[0], mScrollOffset[1]);
}
mNestedOffsets[0] += mScrollOffset[0];
mNestedOffsets[1] += mScrollOffset[1];
} else if (ViewCompat.getOverScrollMode(this) != ViewCompat.OVER_SCROLL_NEVER) {
if (ev != null) {
pullGlows(ev.getX(), unconsumedX, ev.getY(), unconsumedY);
}
considerReleasingGlowsOnScroll(x, y);
}
Как мы видим здесь, на javadoc для dispatchNestedScroll (часть API NestedScrollingChild), если есть один родитель, который потребляет прокрутку, RecyclerView не будет применять какую-либо анимацию overscroll (красное свечение).
AppBarLayout потребляет прокрутку, а точнее, пока существует NestedScrollingParent, который возвращает true на onStartNestedScroll, перепрограммирование анимации не произойдет.
CoordinatorLayout - это NestedScrollingParent, но не возвращает true, если не существует CoordinatorLayout.Behavior. Поведение по умолчанию AppBarLayout реализует этот метод metdo, чтобы вернуть true, когда есть вертикальная прокрутка. + AppBarLayout имеет что-то прокручивать + просмотр, достаточно большой для прокрутки.
// Return true if we're nested scrolling vertically, and we have scrollable children
// and the scrolling view is big enough to scroll
final boolean started = (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0
&& child.hasScrollableChildren()
&& parent.getHeight() - directTargetChild.getHeight() <= child.getHeight();
Flinging использует несколько иной подход, позволяя выполнять анимацию overscroll независимо от того, использует ли NestedScrollingParent прокрутку.
if (!dispatchNestedPreFling(velocityX, velocityY)) {
final boolean canScroll = canScrollHorizontal || canScrollVertical;
dispatchNestedFling(velocityX, velocityY, canScroll);
if (canScroll) {
velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity));
velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity));
mViewFlinger.fling(velocityX, velocityY);
return true;
}
}
Честно говоря, я не могу сказать, является ли это ошибкой, потому что логика имеет смысл. Если вы прокручиваете верхнюю часть представления и у вас есть что-то похожее на CollapsingToolbar, вы не хотите, чтобы анимация overscoll произошла. Однако есть способ сделать так, чтобы поведение могло поглощать количество прокрутки x/y, чтобы остановить анимацию. Также странно, что оба кода для прокрутки и отбрасывания различны.