CollapsingToolbarLayout расширяется, только когда находится наверху

У меня проблемы с AppBarLayout и CollapsingToolbarLayout. Вот что сейчас происходит:

https://www.youtube.com/watch?v=z4yD8rmjSjU

Прокрутка вниз - это именно то, что мне нужно. Однако, когда я снова прокручиваю вверх, оранжевая полоса должна появляться немедленно (что и происходит), но я хочу, чтобы ImageView начинал появляться только тогда, когда пользователь прокручивает до самого верха. Может ли кто-нибудь помочь мне добиться такого эффекта?

Это мой макет xml:

<android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|enterAlways|exitUntilCollapsed">

        <TextView
                android:text="ImageView"
                android:textSize="20sp"
                android:textColor="@android:color/white"
                android:gravity="center"
                android:layout_marginTop="56dp"
                android:layout_width="match_parent"
                android:layout_height="145dp"
                app:layout_collapseMode="parallax"
                android:background="#444"/>

        <TextView
                android:text="Top bar"
                android:textColor="@android:color/white"
                android:gravity="center_vertical"
                android:paddingStart="16dp"
                android:paddingEnd="16dp"
                android:layout_width="match_parent"
                android:layout_height="56dp"
                android:background="#ff8000"
                app:layout_collapseMode="pin"/>

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

    <TextView
            android:text="Bottom bar"
            android:gravity="center_vertical"
            android:paddingStart="16dp"
            android:paddingEnd="16dp"
            android:layout_width="match_parent"
            android:textColor="@android:color/black"
            android:layout_height="50dp"
            android:background="#ddd"
            app:layout_scrollFlags="enterAlways"/>


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

<include layout="@layout/content_scrolling"/>




Ответы (5)


Настроить CoordinatorLayout поведение сложно. Вы хотите, чтобы оранжевая полоса отображалась немедленно, а ImageView - только после прокрутки содержимого вверх, но эти представления принадлежат одному родительскому CollapsingToolbarLayout, и оба получают либо поведение, которое у вас есть сейчас или противоположное с флагом enterAlwaysCollapsed. Я не вижу способа разделить поведение этих представлений, не вмешиваясь в CoordinatorLayout / CollapsingToolbarLayout Java API.

Если более простое поведение не вариант, и никто здесь не указывает на простое решение, я предлагаю попробовать относительно новый MotionLayout вместо танцев с CollapsingToolbarLayout внутренностями, в конечном итоге вы сэкономите много времени. Вначале будет немного сложнее, но это дает четкие возможности для настройки. Вот очень хорошая статья, в которой показано, как создать UX, похожий на до CoordinatorLayout, но с использованием MotionLayout. И вторая часть этой статьи с некоторыми дополнительными настройками.

person Dmide    schedule 24.03.2019

В итоге я переместил оранжевую полосу из CollapsingToolbarLayout и установил OnOffsetChangedListener, который изменяет translationY верхней панели на AppBarLayout.

Установка OnOffsetChangedListener:

app_bar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appbar, offset ->

    topbar.translationY = Math.min(image.height.toFloat(),  - offset.toFloat())

})

Макет:

<android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <TextView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:id="@+id/topbar"
            app:elevation="8dp"
            android:elevation="8dp"
            android:background="#ff8000"
            android:gravity="center_vertical"
            android:paddingStart="16dp"
            android:paddingEnd="16dp"
            android:text="Top bar"
            android:textColor="@android:color/white"
            app:layout_scrollFlags="scroll|enterAlways" />

    <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/image"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed">

        <TextView
                android:layout_width="match_parent"
                android:layout_height="145dp"
                android:background="#444"
                android:gravity="center"
                android:text="ImageView"
                android:textColor="@android:color/white"
                android:textSize="20sp"
                app:layout_collapseMode="parallax" />


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

    <TextView
            android:id="@+id/bottombar"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            app:elevation="8dp"
            android:elevation="8dp"
            android:background="#ddd"
            android:gravity="center_vertical"
            android:paddingStart="16dp"
            android:paddingEnd="16dp"
            android:text="Bottom bar"
            android:textColor="@android:color/black"
            app:layout_scrollFlags="enterAlways" />
</android.support.design.widget.AppBarLayout>

<android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <include layout="@layout/content_scrolling"/>

</android.support.v4.widget.NestedScrollView>

person Mark Buikema    schedule 25.03.2019

Есть много эффектов на поведение прокрутки, которые могут быть достигнуты путем установки различных layout_scrollFlags. В вашем случае, я думаю, вам нужен флаг enterAlwaysCollapsed. Добавьте флаг вместе с enterAlways вместо замены всех флагов.

scroll заставит панель инструментов прокручиваться, как и остальное содержимое, enterAlways заставит панель инструментов И остальную часть CollapsingToolbarLayout вернуться сразу после прокрутки вверх, тогда как enterAlwaysCollapsed разворачивает CollapsingToolbarLayout только после прокрутки страницы до конца.

Вот эффект, достигнутый enterAlwaysCollapsed.

person Jack    schedule 24.03.2019
comment
меня устраивает! enterAlwaysCollapsed - это как раз то, что мне нужно - person Andy; 25.07.2020
comment
Отлично, спасибо! - person DIRTY DAVE; 21.02.2021

Я думаю, вы можете управлять этим из своего кода, я пробовал это, просто обнаруживая поведение макета

 app_bar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {

        if (Math.abs(verticalOffset)-appBarLayout.getTotalScrollRange() == 0)
        {
            //  Collapsed


        }
        else
        {
            //Expanded


        }
    }
});
person Richa Shah    schedule 25.03.2019

Попробуй @ Mark. У меня есть свиток, который ты показал в видео.

<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">
<android.support.design.widget.AppBarLayout
    android:id="@+id/app_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.design.widget.CollapsingToolbarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_scrollFlags="scroll|enterAlways|exitUntilCollapsed">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="145dp"
            android:layout_marginTop="56dp"
            android:background="#444"
            android:gravity="center"
            android:text="ImageView"
            android:textColor="@android:color/white"
            android:textSize="20sp"
            app:layout_collapseMode="parallax" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:background="#ff8000"
            android:gravity="center_vertical"
            android:paddingStart="16dp"
            android:paddingEnd="16dp"
            android:text="Top bar"
            android:textColor="@android:color/white"
            app:layout_collapseMode="pin" />

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

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#ddd"
        android:gravity="center_vertical"
        android:paddingStart="16dp"
        android:paddingEnd="16dp"
        android:text="Bottom bar"
        android:textColor="@android:color/black"
        app:layout_scrollFlags="enterAlways" />
</android.support.design.widget.AppBarLayout>


<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <include layout="@layout/content_scrolling"/>

</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
person Brahma Datta    schedule 25.03.2019
comment
Изображение по-прежнему появляется сразу после начала прокрутки вверх. Он должен появиться только тогда, когда пользователь снова окажется наверху. - person Mark Buikema; 25.03.2019
comment
Итак, вы хотите, чтобы изображение было скрыто, когда пользователь прокручивает страницу вверх? @MarkBuikema - person Brahma Datta; 25.03.2019
comment
Да, изображение должно быть скрыто, пока пользователь не прокрутил его до самого верха. - person Mark Buikema; 25.03.2019
comment
Я сделал эту функцию такой же, как и на видео. Изображение не появится до тех пор, пока пользователь не увидит вид сверху. После того, как он станет видимым, появится изображение. Или я что-то упустил? - person Brahma Datta; 25.03.2019
comment
Я ответил на свой вопрос, проверьте. Изображение не должно появляться, пока список не окажется вверху. - person Mark Buikema; 25.03.2019