Lollipop AppBarLayout/ Панель инструментов отсутствует анимация прокрутки
Используя самый простой пример с AppBarLayout и панелью инструментов, я не могу видеть анимацию перезаписи (свечение снизу и сверху) при попытке прокрутить больше. Однако, если вы бросите контент, он покажет его.
Вот код (nav_drawer_toolbar_layout.xml):
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Replace fragments in this content frame, like a RecycleView -->
<FrameLayout
android:id="@+id/content_frame"
app:layout_behavior="android.support.design.widget.AppBarLayout$ScrollingViewBehavior"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:minHeight="?attr/actionBarSize"
app:titleTextAppearance="@style/Base.TextAppearance.AppCompat.Title"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways"/>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
Вслед за простой класс деятельности:
public class MyActivity extends AppCompatActivity implements {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.nav_drawer_toolbar_layout);
// Setup the toolbar/actionbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FragmentManager manager = getFragmentManager();
manager.beginTransaction().replace(R.id.content_frame, new MyFragmentList).commit();
}
}
MyFragmentList - это фрагмент с RecycleView с содержимым для прокрутки приложения.
Однако, если я удалю AppBarLayout из xml и оставлю панель инструментов открытой (просто прокомментируем открытие и закрытие AppBarLayout), при прокрутке будет отображаться анимация перезаписи (свечение).
Или если вы удалите layout_scrollFlags="scroll"
тогда прокрутка работает, но вы не можете скрыть панель действий при прокрутке.
Для дополнительной информации отладка RecycleView, строка 2272
if(this.mBottomGlow != null && !this.mBottomGlow.isFinished()) {
всегда завершается при включении AppBarLayout и не завершается, когда его там нет. Что-то переписывает события касания?
Кто-нибудь знает, кому показывать анимацию перезаписи (свечение) с AppBarLayout?
1 ответ
РЕДАКТИРОВАТЬ: Кажется, есть билет для этой ошибки. Вы можете определенно сделать то, что сделал artur.dr... @ gmail.com и расширить RecyclerView, чтобы переопределить RecyclerView # dispatchNestedScroll, чтобы всегда возвращать false (он пишет true в своем отчете), вы можете заставить работать анимацию избыточной прокрутки, хотя я уверен, что это может что-то сломать.
К сожалению, как кодируется RecyclerView и как создается API NestedScrollingChild, нет никакого чистого способа получить желаемое поведение.
Это из 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 не будет применять анимацию избыточной прокрутки (свечение краев).
AppBarLayout действительно использует прокрутку, более конкретно, пока есть NestedScrollingParent, который возвращает true на onStartNestedScroll, анимации избыточной прокрутки не будет.
CoordinatorLayout является NestedScrollingParent, но не возвращает true, если только не существует CoordinatorLayout.Behavior, который это делает. Поведение AppBarLayout по умолчанию реализует этот метод для возврата 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 использует немного другой подход, позволяющий анимации с избыточной прокруткой происходить независимо от того, использует ли 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, вы не хотите, чтобы происходила анимация переполнения. Однако есть способ сделать так, чтобы поведение могло потреблять количество прокрутки x/y, чтобы остановить анимацию. Также странно, что оба кода для прокрутки и броска различны.