Подтвердить что ты не робот

Lollipop AppBarLayout/панель инструментов отсутствует анимация прокрутки

используя самый простой пример с AppBarLayout и панелью инструментов, при попытке прокрутки больше не вижу анимацию overscroll (свечение сверху или снизу). Однако, если вы отправляете контент, он покажет его.

Вот код (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), она покажет анимацию overscroll (свечение) при прокрутке.

Или, если вы удалите layout_scrollFlags="scroll", то прокрутка работает, но вы не можете заставить панель действий скрываться при прокрутке.

За дополнительной информацией, отладки RecycleView, строка 2272

if(this.mBottomGlow != null && !this.mBottomGlow.isFinished()) {

всегда заканчивается при включении AppBarLayout и не завершается, когда его нет. Что-то переписывает свои события касания?

Кто-нибудь знает, кто будет показывать анимацию overscroll (свечение) с помощью AppBarLayout?

4b9b3361

Ответ 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, чтобы остановить анимацию. Также странно, что оба кода для прокрутки и отбрасывания различны.