web-dev-qa-db-fra.com

Ajouter un comportement de défilement de la barre d'application à plusieurs vues dans CoordinatorLayout

Je souhaite ajouter la prise en charge du défilement à plus d’une vue enfant unique et défilable de CoordinatorLayout conjointement avec un AppBarLayout et CollapsingToolbarLayout. Lorsque vous faites défiler le RecyclerView ou le AppBarLayout (code condensé ci-dessous), la barre d’applications et son contenu défilent et se replient avec succès. Cependant, lorsque vous tentez d'initier un événement de défilement sur le LinearLayout au-dessus de RecyclerView, rien ne se produit car le LinearLayout ne sait pas faire défiler ou réduire la vue.

Le but est que le LinearLayout agisse comme un en-tête collant pour le RecyclerView et le pied de page pour le AppBarLayout et reçoive le même comportement de défilement que le RecyclerView, semblable à lecture aléatoire de Spotify/en-tête hors connexion disponible . En fait, ce serait bien si le appbar_scrolling_view_behaviorlayout_behavior pourrait être appliqué au LinearLayout de la même façon que le RecyclerView, mais j'imagine que le comportement est ignoré sur les vues non défilables. Quelqu'un a-t-il connaissance d'une solution de contournement pour cela qui n'exige pas la mise en place de la vue LinearLayout sous la forme d'une ligne dans le RecyclerView?

<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.support.design.widget.AppBarLayout
        Android:id="@+id/app_bar_layout"
        Android:layout_width="match_parent"
        Android:layout_height="@dimen/collapsible_app_bar_height"
        Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <Android.support.design.widget.CollapsingToolbarLayout
            Android:id="@+id/collapsing_toolbar_layout"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:background="@drawable/gradient_banner"
            app:contentScrim="@color/background_content_frame"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                Android:id="@+id/image_header"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                Android:src="@drawable/some_image"
                app:layout_collapseMode="parallax"/>

            <Android.support.v7.widget.Toolbar
                Android:id="@+id/collapsible_toolbar"
                Android:layout_width="match_parent"
                Android:layout_height="?attr/actionBarSize"
                Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:layout_collapseMode="pin"/>

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

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

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="@dimen/slide_handle_height"
        Android:orientation="horizontal"
        Android:background="@color/slide_handle"
        Android:gravity="center_vertical">

        <!-- three buttons -->

    </LinearLayout>

    <Android.support.v7.widget.RecyclerView
        Android:id="@+id/recycler_view"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_marginTop="@dimen/slide_handle_height"
        Android:scrollbars="vertical"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</Android.support.design.widget.CoordinatorLayout>
39
Ryan

Après quelques essais et erreurs, voici la version condensée de la présentation qui a finalement fonctionné pour moi:

<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:id="@+id/coordinator_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

<Android.support.design.widget.AppBarLayout
    Android:id="@+id/app_bar_layout"
    Android:layout_width="match_parent"
    Android:layout_height="@dimen/collapsible_app_bar_height"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <Android.support.design.widget.CollapsingToolbarLayout
        Android:id="@+id/collapsing_toolbar_layout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:contentScrim="@color/background_content_frame"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <ImageView
            Android:id="@+id/image_header"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:layout_gravity="center_horizontal"
            Android:layout_marginBottom="@dimen/button_bar_height"
            Android:scaleType="centerCrop"
            Android:background="@Android:color/transparent"
            Android:src="@drawable/default_header"
            Android:contentDescription="@string/description_content_image"
            app:layout_collapseMode="parallax"/>

        <ImageView
            Android:id="@+id/image_header_gradient"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:layout_marginBottom="@dimen/button_bar_height"
            Android:src="@drawable/scrim_top_bottom_banner"
            app:layout_collapseMode="parallax"
            tools:ignore="ContentDescription"/>

        <Android.support.v7.widget.Toolbar
            Android:id="@+id/collapsible_toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="104dp"
            Android:minHeight="?attr/actionBarSize"
            Android:gravity="top"
            Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:contentInsetStart="0dp"
            app:titleMargins="0dp"
            app:layout_collapseMode="pin"/>

        <RelativeLayout
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layout_marginStart="@dimen/landing_header_button_margin_horizontal"
            Android:layout_marginEnd="@dimen/landing_header_button_margin_horizontal"
            Android:layout_marginBottom="@dimen/button_bar_height"
            Android:layout_gravity="bottom"
            Android:gravity="center_vertical"
            app:layout_collapseMode="parallax">

            <Button
                Android:id="@+id/button_one"
                Android:layout_alignParentStart="true"
                Android:drawableStart="@drawable/selector_one"
                Android:textColor="@color/alabaster_white"
                Android:visibility="gone"
                style="@style/Button.TextCount"/>

            <Button
                Android:id="@+id/button_two"
                Android:layout_alignParentEnd="true"
                Android:layout_gravity="end"
                Android:drawableStart="@drawable/selector_two"
                Android:textColor="@color/alabaster_white"
                Android:visibility="gone"
                style="@style/Button.TextCount"/>

        </RelativeLayout>

        <LinearLayout
            Android:layout_width="match_parent"
            Android:layout_height="@dimen/button_bar_height"
            Android:layout_gravity="bottom"
            Android:gravity="center_vertical"
            Android:orientation="horizontal"
            Android:background="@color/slide_handle">

            <!-- three buttons -->

        </LinearLayout>

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

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

<Android.support.v7.widget.RecyclerView
    Android:id="@+id/recycler_view"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:scrollbars="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
6
Ryan

Vous n'avez pas besoin d'une solution de contournement ou de quelque chose d'étrange. Ce comportement est pris en charge par la bibliothèque. Il suffit de remplacer votre LinearLayout par ceci et de le placer sous le RecyclerView:

<Android.support.v4.widget.NestedScrollView
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical"
        Android:gravity="center">

        <Button
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:padding="15dp"
            Android:text="Button text"/>

    </LinearLayout>

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

Aussi, vous devrez mettre ceci dans votre RecyclerView pour le montrer derrière LinearLayout:

    Android:paddingTop="30dp"
    Android:clipToPadding="false"

Voici à quoi cela ressemblerait:

<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.support.design.widget.AppBarLayout
    Android:id="@+id/app_bar_layout"
    Android:layout_width="match_parent"
    Android:layout_height="@dimen/collapsible_app_bar_height"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <Android.support.design.widget.CollapsingToolbarLayout
        Android:id="@+id/collapsing_toolbar_layout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:background="@drawable/gradient_banner"
        app:contentScrim="@color/background_content_frame"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">

        <ImageView
            Android:id="@+id/image_header"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:src="@drawable/some_image"
            app:layout_collapseMode="parallax"/>

        <Android.support.v7.widget.Toolbar
            Android:id="@+id/collapsible_toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="?attr/actionBarSize"
            Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:layout_collapseMode="pin"/>

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

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

<Android.support.v7.widget.RecyclerView
    Android:id="@+id/recycler_view"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_marginTop="@dimen/slide_handle_height"
    Android:scrollbars="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    Android:paddingTop="30dp"
    Android:clipToPadding="false"/>

<Android.support.v4.widget.NestedScrollView
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical"
        Android:gravity="center">

        <Button
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:padding="15dp"
            Android:text="Button text"/>

    </LinearLayout>

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

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

Ce n'est pas un beau design, mais c'est une solution. Vous pouvez placer un Layout plus agréable à l'intérieur du LinearLayout pour qu'il ressemble à Spotify.

Edit: Vidéo ajoutée

Demo videoDemo video 2

46
Mario Velasco

Ceci est un en-tête collant placé au milieu entre Toolbar et RecyclerView:

<Button
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:layout_anchor="@+id/app_bar_layout"
    app:layout_anchorGravity="center|bottom"
    Android:text="Shuffle Play"/>

Pour éviter les chevauchements avec le Toolbar, vous pouvez définir différentes hauteurs sur AppBarLayout et CollapsingToolbarLayout:

<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/main_content"
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="240dp"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    Android:fitsSystemWindows="true">

    <Android.support.design.widget.CollapsingToolbarLayout
        Android:id="@+id/collapsing_toolbar"
        Android:layout_width="match_parent"
        Android:layout_height="210dip"
        Android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        Android:fitsSystemWindows="true"
        app:contentScrim="?attr/colorPrimary"
        app:expandedTitleMarginStart="48dp"
        app:expandedTitleMarginBottom="30dp"
        app:expandedTitleMarginEnd="64dp">

        <ImageView
            Android:id="@+id/backdrop"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:scaleType="centerCrop"
            Android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax" />

        <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"
            app:layout_collapseMode="pin" />
    </Android.support.design.widget.CollapsingToolbarLayout>

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


<Android.support.v7.widget.RecyclerView
    Android:id="@+id/recycler_view"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_marginTop="@dimen/slide_handle_height"
    Android:scrollbars="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

<Button
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:layout_anchor="@id/appbar"
    app:layout_anchorGravity="center|bottom"
    Android:text="Shuffle Play"/>
</Android.support.design.widget.CoordinatorLayout>

Démo vidéo:

Demo video

En outre, vous pouvez définir une hauteur sur Toolbar mais vous devrez créer un titre personnalisé avec un comportement personnalisé tel que ce projet CoordinatorLayoutExample . Je l'ai fait avec un titre personnalisé sans comportement:

<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/main_content"
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="240dp"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    Android:fitsSystemWindows="true">

    <Android.support.design.widget.CollapsingToolbarLayout
        Android:id="@+id/collapsing_toolbar"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        Android:fitsSystemWindows="true"
        app:collapsedTitleTextAppearance="@style/TransparentText"
        app:expandedTitleTextAppearance="@style/TransparentText"
        app:contentScrim="?attr/colorPrimary">

        <ImageView
            Android:id="@+id/backdrop"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:scaleType="centerCrop"
            Android:fitsSystemWindows="true"
            app:layout_collapseMode="parallax" />

        <Android.support.v7.widget.Toolbar
            Android:id="@+id/toolbar"
            Android:layout_height="80dp"
            Android:layout_width="match_parent"
            Android:minHeight="?attr/actionBarSize"
            Android:gravity="top"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_collapseMode="pin" >
            <TextView
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:text="Title"
                Android:textSize="20sp"
                Android:textColor="@Android:color/white"/>
        </Android.support.v7.widget.Toolbar>
    </Android.support.design.widget.CollapsingToolbarLayout>

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


<Android.support.v7.widget.RecyclerView
    Android:id="@+id/recycler_view"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_marginTop="@dimen/slide_handle_height"
    Android:scrollbars="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

<Button
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:layout_anchor="@id/appbar"
    app:layout_anchorGravity="center|bottom"
    Android:text="Shuffle Play"/>
</Android.support.design.widget.CoordinatorLayout>

Modes:

<style name="TransparentText" parent="@Android:style/TextAppearance">
    <item name="Android:textColor">#00000000</item>
</style>

Démo vidéo:

enter image description here

8
Mario Velasco

L'approche de Ryan est bonne mais peut-être un peu compliquée. Vous pouvez obtenir le même effet plus facilement en utilisant les attributs de CoordinatorLayout pour ses enfants. Utilisation

layout_anchor="@id/app_bar_layout"

et

layout_anchorGravity="bottom|right|end"

dans une vue (contenant vos boutons) et placez-le sous le Toolbar. Augmentez également l’altitude de cette vue car, lorsque vous faites défiler l'écran, Toolbar chevauchera votre vue.

3
George Kravas

Tu peux essayer ça

    <Android.support.design.widget.CoordinatorLayout>
         <Android.support.design.widget.AppBarLayout>
             <!-- another xml code -->
         </<Android.support.design.widget.AppBarLayout>

         <Android.support.v4.widget.NestedScrollView
              Android:layout_width="match_parent"
              Android:layout_height="match_parent"              
              app:layout_behavior="Android.support.design.widget.AppBarLayout$ScrollingViewBehavior">

<!-- your recyler view or button or textview xml code -->        
   </Android.support.v4.widget.NestedScrollView>

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

ou

vous pouvez écrire ce code en strings.xml

<string name="appbar_scrolling_view_behavior" translatable="false">Android.support.design.widget.AppBarLayout$ScrollingViewBehavior</string>

et vous pouvez utiliser:

app:layout_behavior="@strings/appbar_scrolling_view_behavior">
3