Сворачивание макета при прокрутке в Android

Я хотел бы, чтобы пользовательское представление свернулось с переходом во время прокрутки.

У меня AppBarLayout с Toolbar внутри. Ниже этого есть пользовательское представление, которое я хочу свернуть.

Под пользовательским представлением есть NestedScrollView с LinearLayout.

Панель инструментов — зеленая, пользовательский макет — розовый, а прокрутка с линейкой — серая:

настраиваемый вид панели инструментов

После прокрутки вниз:

прокрутить вниз

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        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"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    </android.support.design.widget.AppBarLayout>


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="170dp"
        android:layout_marginTop="?attr/actionBarSize"
        android:background="@drawable/background"
        android:gravity="center">
    </RelativeLayout>

    <ScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="170dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <include
            layout="@layout/linear"
            android:layout_marginBottom="20dp"
            android:layout_marginTop="20dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </ScrollView>

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

Должен ли я использовать собственное поведение и CoordinatorLayout или перевод с NestedScroll с анимацией перевода?


comment
Что касается меня, я бы обернул ваше пользовательское представление в CollapsingToolbarLayout и использовал собственное поведение. Или вы можете использовать OnOffsetChangedListener из AppBarLayout для этого перехода.   -  person romtsn    schedule 01.07.2017
comment
@ rom4ek Можно ли разместить два вида изображений в произвольном месте на CollapsingToolbarLayout?   -  person pixel    schedule 02.07.2017
comment
Вы можете оставить их в том же RelativeLayout, что и сейчас. Просто поместите этот RelativeLayout внутрь CollapsingToolbarLayout.   -  person romtsn    schedule 02.07.2017
comment
@ rom4ek, но верхняя панель инструментов (с ящиком) остается нетронутой, а CollapsingToolbarLayout предназначен для использования внутри AppBarLayout   -  person pixel    schedule 02.07.2017
comment
Да, ты прав. Но вам не нужно держать панель инструментов внутри AppBarLayout. Вы можете вытащить его из AppBarLayout и поместить сразу после AppBarLayout в свой xml. Таким образом, ваш AppBarLayout будет содержать только CollapsingToolbarLayout с вашим пользовательским представлением внутри. Проверьте мой ответ stackoverflow.com/a/44647978/3225458, это не совсем то, чего вы хотите достичь, но вы можете понять хотя бы структуру xml из него.   -  person romtsn    schedule 03.07.2017
comment
@ rom4ek да, тогда я могу использовать поведение, но неожиданный побочный эффект заключается в том, что моя панель инструментов теряет функции нажатия кнопки «вверх», а тень, которая должна быть под панелью инструментов, отображается в системном окне вверху   -  person pixel    schedule 03.07.2017
comment
@ rom4ek - я понял. Вам нужно обернуть это Toolbar в дополнительные AppBarLayout   -  person pixel    schedule 03.07.2017
comment
круто, рад помочь. Я бы попробовал реализовать это поведение, но сейчас не хватает времени :(   -  person romtsn    schedule 03.07.2017
comment
@rom4ek у вас есть библиотека для таких вещей? :)   -  person pixel    schedule 03.07.2017
comment
Нет, такой библиотеки у меня нет, но есть планы на нее :)   -  person romtsn    schedule 04.07.2017
comment
Давайте продолжим обсуждение в чате.   -  person pixel    schedule 04.07.2017


Ответы (2)


Используйте библиотеку Observable ScrollView https://github.com/ksoichiro/Android-ObservableScrollView

person Ramees    schedule 04.07.2017

Мне удалось сделать это без какой-либо библиотеки. Ключевым моментом было наличие двух макетов панели приложений: один с заполнителем и сворачивающимся макетом панели инструментов, который был скрыт в пользовательском представлении, а второй — обычный.

Затем я создал два поведения — одно для изменения высоты вложенного макета, а второе — для управления внутренними представлениями внутри пользовательского представления.

Вот мой макет:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<android.support.design.widget.AppBarLayout
    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|exitUntilCollapsed"
        app:titleEnabled="false">

        <View
            android:id="@+id/vieItemDetailsPlaceholder"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#00000000" />

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

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

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

    <android.support.v7.widget.Toolbar
        android:id="@+id/second_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.AppBarLayout>

<android.support.v4.widget.NestedScrollView
    android:id="@+id/detailContent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="com.example.detail.view.Det ailScrollBehavior">

    <include
        layout="@layout/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp" />

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

<!-- second layout with behavior -->
<include layout="@layout/two_circles_layout" />

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

Подробное поведение прокрутки:

public class DetailScrollBehavior extends Behavior<NestedScrollView> {

    private final Context context;

    public DetailScrollBehavior(Context context, AttributeSet attrs) {
        this.context = context;
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, NestedScrollView child, View dependency) {
        return dependency.getId() != R.id.ablItemDetailsSecondToolbar && dependency instanceof AppBarLayout;
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, NestedScrollView child, View dependency) {
        int minHeight = context.getResources().getDimensionPixelSize(R.dimen.some_min_height);
        int placeholderHeight = getPlaceholderHeight(dependency);
        int actionBarHeight = getActionBarHeight(context.getTheme());

        if (placeholderHeight < minHeight + actionBarHeight) {
            placeholderHeight = minHeight + actionBarHeight;
        }

        child.setPadding(0, placeholderHeight, 0, 0);

        return true;
    }
}

и часть two_circles_layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/relDetailsContainer"
    android:layout_width="match_parent"
    android:layout_height="@dimen/team_vs_details_height"
    android:layout_marginTop="?attr/actionBarSize"
    android:background="@drawable/background"
    android:gravity="center"
    app:layout_behavior="com.example.DetailBehavior"
    tools:showIn="@layout/activity_item_detail">


    [ ... ]

</RelativeLayout>
person pixel    schedule 20.07.2017
comment
Не могли бы вы опубликовать содержимое two_circles_layout.xml и пользовательские поведения? - person Ivan Narvaez; 04.04.2019
comment
у вас есть какое-нибудь обучающее видео / написанное, чтобы изучить этот материал? Я долго искал? - person Lidor Eliyahu Shelef; 19.01.2021
comment
можете ли вы указать ресурс на строки: - (app:layout_behavior=com.example.detail.view.DetailScrollBehavior) - (layout=@layout/content) - (layout=@layout/two_circles_layout) Все они выдают ошибки :( - person Lidor Eliyahu Shelef; 19.01.2021
comment
@LidorEliyahuShelef добавил - person pixel; 20.01.2021
comment
@пиксель в two_circles_layout в области [ . . . ] что должно было быть? Я имею в виду, это начальный макет или окончательный макет, или это макет, в который вы перемещаете его взгляд внутрь и меняете их? - person Lidor Eliyahu Shelef; 20.01.2021
comment
Эти элементы макета, такие как круги и т. Д., Я отредактировал их, поскольку они не являются ключом к ответу. - person pixel; 20.01.2021
comment
Это важно, потому что DetailScrollBehavior имеет красные ошибки, и нам нужно знать, какая из них что означает, а также DetailScrollBehavior не распознает методы getPlaceholderHeight и getActionBarHeight. плюс ты не сказал что за @layout/content b/c он выдает и там тоже ошибка - person Lidor Eliyahu Shelef; 21.01.2021