Design Support Library : Le CollapsingToolbarLayout

La nouvelle bibliothèque de design présentée par Google (Vous pouvez trouver un tuto de présentation ici : Design Support Library), possède énormément de composants que vous pouvez inclure dans vos applications Android. Parmi eux, on trouve le CollapsingToolbarLayout qui permet de créer une barre d’action (Toolbar) réductible. Par exemple, vous pouvez avoir une image, qui se réduira au fur et à mesure que le contenu en dessous scroll pour se transformer en Toolbar. Rien de mieux qu’une petite vidéo pour illustrer cet exemple un peu flou :

Description de l’exemple

L’exemple qui sera abordé tout au long de ce tutoriel, se compose d’:

  • Une toolbar (Cliquez-ici pour voir le tuto traitant de l’intégration de la Toolbar),
  • Une image,
  • Une liste (RecyclerView)

CordinatorLayout et AppBarLayout

Les notions de CoordinatorLayout et AppBarLayout sont présentées car nécessaire pour l’implémentation de l’exemple.

Le CoordinatorLayout permet de définir des règles entres les différents composants qu’il inclue (image, zone de texte, liste …) ainsi que le comportement qu’aura chaque composant quand l’un des autres composants se met à jour (scroll, déplacement …).

L’AppBarLayout est un LinearLayout vertical qui implémente beaucoup de concept du material design pour les barres d’actions et cela notamment lors du scroll. 
Chaque composant (élément fils) de l’AppBarLayout doit indiquer la manière dont il souhaite se comporter lors du scroll et cela soit à l’aide de la méthode setScrollFlags ou l’attribut app:layout_scrollFlags.

Pour que tous les comportements de l’AppBarLayout se comporte de la manière souhaités, il doit être utilisé en combinaison avec le CoordinatorLayout. Ainsi, qu’un élément scrollable (ListView, RecyclerView) déclaré dans le CoordinatorLayout mais à l’extérieur de l’AppBarLayout.

Implémentation

Pour commencer, il faut inclure dans le fichier gradle les différentes dépendances utilisées dans le projet.

compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.android.support:design:22.2.0'
compile 'com.android.support:recyclerview-v7:22.2.0'

Puis nous allons construire l’exemple étape par étape.

1 – Déclarer le CoordinatorLayout.

Déclarer le CoordinatorLayout dans la vue (xml) principale de l’application, rien de bien compliqué.

<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"
    tools:context=".MainActivity">

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

2 – Déclarer le AppBarLayout

<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"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

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

3 – Déclarer le CollapsingToolbarLayout

Le CollapsingToolbarLayout est un wrapper pour les Toolbars, il est utilisé en combinaison du AppBarLayout pour implémenter l’effet de toolbar qui se reduit.

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

Il possède plusieurs attributs :

  • app:contentScrim : Permet de spécifier le drawable (image, background) utilisée par la Toolbar quand il est au top de la vue.
  • app:expandedTitleMarginEnd : Spécifier le margin à la fin du titre (de la toolbar) lorsque celle ci est déployer
  • app:expandedTitleMarginStart : Spécifier le margin au début du titre (de la toolbar) lorsque celle ci est déployer
  • app:scrollFlags : Cet attribut permet de spécifier le comportement du composant quand l’élément rentre dans le scroll et quitte le scroll

L’attribut scrollFlags possède les deux valeurs suivantes :

  • scroll (indispensable pour les éléments qui doivent scroller en dehors de l’écran, les vues qui utilisent pas cette valeur reste fixer en haut de l’écran),
  • enterAlways (Assure que tout scroll vers le bas rend cette élément visible).

La déclaration de l’AppBarLayout est très simple, la seule spécificité est qu’il possède un thème. Ce thème est celui disponible dans AppCompat android et plus précisément celui qui défini une toolbar noire.

Il faut ensuite déclarer le contenu de l’AppBarLayout, dans notre cas, ça sera une Image et une Toolbar

<ImageView
 android:id="@+id/backgroundImageView"
 android:layout_width="match_parent"
 android:layout_height="250dp"
 android:src="@drawable/tigre"
 android:scaleType="centerCrop"
 app:layout_collapseMode="parallax" />

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

La déclaration de ces deux composants est très simple, le seule élément qui saute aux yeux est l’attribut app:layout_collapseMode. Cet attribut permet de spécifier aux différents composants leur comportement lors du scroll et de qu’elle façon ils se reduisent.
Dans le cas de l’image, cet élément aura pour valeur “parallax”, ce qui indiquera que l’image se réduira en utilisant un effet parallax lors du scroll. Un attribut optionnel peut être utilisé pour indiquer la vitesse du parallax (app:layout_collapseParallaxMultiplier).
Dans le cas de la Toolbar, cet élément aura pour valeur “pin”, ce qui indiquera que la toolbar sera fixée en haut de la vue lors du scroll vers le haut.
Ce qui permet de donner les deux effets voulus :

  • Disparition de l’image au fur et a mesure du scroll (vers le haut) et cela en utilisant un effet parallax
  • Apparition de la Toolbar en haut de la vue

La dernière étape consiste à déclarer la RecyclerView dans le CoordinatorLayout mais à l’extérieur de AppBarLayout.

   <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

L’attribut app:layout_behavior possède la valeur @string/appbar_scrolling_view_behavior, qui permet au CoordinatorLayout de réagir au scroll de la RecyclerView. Du coup le scroll du RecyclerView affecte le AppBarLayout et son contenu.

La variable appbar_scrolling_view_behavior à pour valeur

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

Ce qui donnera pour la vue :

<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"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

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


            <ImageView
                android:id="@+id/backgroundImageView"
                android:layout_width="match_parent"
                android:layout_height="250dp"
                android:src="@drawable/tigre"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

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

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

    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

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

Et du côté de l’activité

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar =   (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ViewCompat.setTransitionName(findViewById(R.id.appBarLayout), "Name");

        CollapsingToolbarLayout collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        collapsingToolbarLayout.setTitle("Titre");
        collapsingToolbarLayout.setExpandedTitleColor(getResources().getColor(android.R.color.transparent));

        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        mAdapter = new MyAdapter(myDataset);
        mRecyclerView.setAdapter(mAdapter);
    }

Voici les différentes etapes :

  • Récupérer et utiliser la Toolbar en tant que barre d’action de l’application.
  • Il faut aussi récupérer le CollapsingToolbarLayout et définir le titre ainsi que la couleur du titre quand ce dernier est non reduit (vers le bas). Dans notre cas le texte sera transparant c’est pour cela qu’il est invisble quand le titre n’est pas en haut de l’écran.
  • Initialiser le RecyclerView et lui fournir un adapter avec les données.

Ce qui donnera le résultat suivant :

Vous pouvez trouver le code du projet ici

N’hésitez pas à me faire vos retours ou poser vos questions.

2 commentaires


  1. Je vous remercie pour ce tutoriel.
    Par contre ce tutoriel est incomplet.
    Vous avez détaillé le fichier XML, par contre vous avez parlé brièvement du fichier java (déclaration des variables, création de la classe adapter).
    Il faut aussi préciser l’API que vous avez utilisé.

    Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *