AppBarLayout не рушится во время программной прокрутки

У меня есть ViewPager с фрагментами, которые содержат RecyclerViews. CollapsingTollbarLayout находится над ViewPager. Все работает нормально, за исключением программной прокрутки RecyclerView. Тогда AppBarLayout или CollapsingToolbarLayout не отвечают.

Вот мой базовый макет xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appBarLayout"
    android:layout_width="match_parent"
    android:layout_height="256dp"
    android:fitsSystemWindows="true"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:layout_behavior="de.wackernagel.playball.ui.FlingBehaviour">

    <android.support.design.widget.CollapsingToolbarLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:id="@+id/collapsingToolbarLayout"
        app:contentScrim="?attr/colorPrimary"
        app:titleEnabled="false"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <ImageView
            android:contentDescription="@null"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:src="@drawable/showdown"
            app:layout_collapseMode="parallax"/>

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/doubleActionBarSize"
            android:minHeight="?attr/actionBarSize"
            android:gravity="top"
            app:titleMarginTop="14dp"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@android:color/transparent"
            android:layout_gravity="bottom"
            app:tabTextColor="#BEFFFFFF"
            app:tabSelectedTextColor="#FFFFFFFF"
            app:tabContentStart="@dimen/keyline_2"
            app:tabMode="scrollable" />

    </android.support.design.widget.CollapsingToolbarLayout>

</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

My goal is it to collapse the CollapsingToolbarLayout during a programmatically scroll like a normal touch scroll.

я делаю это по

Activity get Fragment at current viewpager position
    Fragment get LayoutManager from RecyclerView
         LayoutManager scrollToPosition x

Поведение прокрутки работает в RecyclerView, но CollapsingToolbarLayout не отвечает.

ИЗМЕНИТЬ

Вот расположение моих фрагментов:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<de.wackernagel.playball.views.EmptyAwareRecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="8dp" />

<TextView
    android:id="@android:id/empty"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"/>


comment
Я написал сообщение о запуске свертывания при обнаружении прокрутки, необходимого для использования dpad (который использует программную прокрутку) novoda.com/blog/fixing-hiding-appbarlayout-android-tv   -  person ataulm    schedule 15.10.2015
comment
@ataulm спасибо за подсказку. Он указывает мне правильное направление.   -  person Happo    schedule 15.10.2015
comment
@ataulm, кстати, ваша техника обнаружения программной прокрутки ( !recyclerView.isInTouchMode() ) не работает. Возможно, это работает только для телевизора из-за отсутствия сенсорного экрана.   -  person Happo    schedule 16.10.2015
comment
Нет, это не работает по другой причине: P isInTouchMode возвращает true, если последнее взаимодействие с пользователем было с помощью касания, а не клавиатуры, dpad, пульта дистанционного управления и т. д.   -  person ataulm    schedule 16.10.2015


Ответы (3)


Решить эту проблему довольно просто, это происходит из-за того, что getNestedScrollingParentForType(type) в NestedScrollingChildHelper#dispatchNestedScroll возвращает null (поддержка версии lib = 27.0.2) для несенсорной прокрутки, поэтому прокрутка не диспетчеризируется. Таким образом, перед программной прокруткой следует сделать следующее:

if (!recyclerView.hasNestedScrollingParent(ViewCompat.TYPE_NON_TOUCH)) {
    recyclerView.startNestedScroll(View.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH);
}
person nikis    schedule 18.01.2018

У меня была такая же проблема: AppBarLayout не рушился, когда NestedScrollView программно прокручивался вниз. Это привело к тому, что Android неверно рассчитал нижнюю часть NestedScrollView при расширении AppBarLayout. Когда он был свернут, он правильно прокручивался вниз, но когда он был развернут, он не прокручивался вниз на величину, равную высоте AppBarLayout. Я нашел простое решение для этого, установив для setExpanded значение false непосредственно перед попыткой прокрутки.

//scroll to the end of NestedScrollView
AppBarLayout appBarLayout = findViewById(R.id.app_bar_layout);
appBarLayout.setExpanded(false, true);
scrollView.post(() -> scrollView.fullScroll(View.FOCUS_DOWN));

... или если не используются лямбда-выражения (например, ‹ Java 8)

//scroll to the end of NestedScrollView
AppBarLayout appBarLayout = findViewById(R.id.app_bar_layout);
appBarLayout.setExpanded(false, true);
scrollView.post(new Runnable() {
    @Override
    public void run() {
        scrollView.fullScroll(View.FOCUS_DOWN);     
    }
});
person smitty1    schedule 08.09.2019

person    schedule
comment
Пожалуйста, добавьте описание - person zohar; 18.11.2015
comment
Я думаю, вам нужно поместить свой tablayout в сторону CollapsingToolbarLayout - person Nima; 18.11.2015