• 20 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 07/12/2020

Ajoutez des onglets à votre ViewPager

Notre application MyAmazingViewPager est super et plutôt jolie, avouons-le ! Cependant, nous aimerions pouvoir la transformer en quelque chose de... plus utile !

Du coup, je vous propose de la faire évoluer en lui ajoutant des onglets (appelés aussi Tabs).

Vous pouvez retrouver l'application MyAmazingViewPager de départ disponible à ce lien.

Implémenter des onglets

L'implémentation d'onglets sur Android passe par la mise en place du composant graphique TabLayout, disponible uniquement dans la librairie Design Support. Pour cela, nous devons l'ajouter à notre projet via Gradle, notre gestionnaire de dépendances :

dependencies {
    
    ...
    
    compile 'com.android.support:design:26.1.0'
}

Une fois la librairie installée, nous allons ajouter la vue TabLayout (créant nos onglets) juste au-dessus de notre ViewPager, dans le layout de MainActivity :

Fichier activity_main.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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:orientation="vertical">

    <!-- 1 | Add TabLayout to handle tabs -->
    <android.support.design.widget.TabLayout
        android:id="@+id/activity_main_tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#B6C9F1"
        app:tabIndicatorColor="@color/colorPrimary"
        app:tabTextColor="#D4E0F8"
        app:tabSelectedTextColor="#fff"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/activity_main_viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

Explications : Nous avons un peu revu le layout de notre activité principale MainActivity. En effet, nous avons maintenant un layout principal (LinearLayout), contenant en premier lieu notre TabLayout, puis en dessous, notre ViewPager.

Nous souhaitons également que chacun des onglets aient un titre différent (Page 1, Page 2, etc...). Mais où allons-nous bien pouvoir définir ce titre ? Et bien directement dans notre adapter PageAdapter :

Extrait du fichier PageAdapter.java :

public class PageAdapter extends FragmentPagerAdapter {
    
    ...
    
    @Override
    public CharSequence getPageTitle(int position) {
        return "Page "+position;
    }
    
}

Explications : La méthode getPageTitle( ) a spécialement été conçue pour retourner le titre de chacune des pages d'un ViewPager. C'est cette méthode qui sera utilisée par notre TabLayout.

Et c'est tout ? Notre implémentation est terminée ? 

Et non ! Il nous reste comme d'habitude à modifier notre MainActivity, qui va expressément faire le lien entre le TabLayout et le ViewPager. 

Extrait du fichier MainActivity.java :

public class MainActivity extends AppCompatActivity {
    
    ...
    
    private void configureViewPagerAndTabs(){
        //Get ViewPager from layout
        ViewPager pager = (ViewPager)findViewById(R.id.activity_main_viewpager);
        //Set Adapter PageAdapter and glue it together
        pager.setAdapter(new PageAdapter(getSupportFragmentManager(), getResources().getIntArray(R.array.colorPagesViewPager)));

        // 1 - Get TabLayout from layout
        TabLayout tabs= (TabLayout)findViewById(R.id.activity_main_tabs);
        // 2 - Glue TabLayout and ViewPager together
        tabs.setupWithViewPager(pager);
        // 3 - Design purpose. Tabs have the same width 
        tabs.setTabMode(TabLayout.MODE_FIXED);
    }
    
}

Explications : Dans cet extrait, nous allons modifier et renommer notre méthode configureViewPager( ) en y ajoutant la configuration de notre TabLayout :

  • Ligne 1 : Nous récupérons et sérialisons notre TabLayout.

  • Ligne 2 : Nous indiquons au TabLayout sur quel ViewPager se rattacher, notamment pour afficher la bonne page en cas de clic sur un onglet.

  • Ligne 3 : Par souci esthétique, nous faisons en sorte que chaque onglet dispose de la même taille et remplisse complètement la largeur de notre écran.

Lancez maintenant l'application et appréciez l'implémentation de votre premier TabLayout. Félicitations !

                                    

Implémenter des fragments indépendants

Maintenant que se passerait-il si nous voulions un design et un comportement différent sur chacune des pages de ce ViewPager ? Une page pourrait-elle par exemple afficher un fil d'actualité, une autre le profil de l'utilisateur, et une dernière les paramètres de l'application ?

Mais du coup nous n'avons qu'un seul fragment, PageFragment, avec un seul layout ! C'est littéralement impossible ! :'(

En l'état des choses oui. Enfin tout est possible en informatique, mais le résultat serait affreux au niveau du code :colere:.

Afin de faire face à cette demande d'indépendance de page, il faudrait créer un fragment différent par page, pour pouvoir y implémenter un design (layout) et un comportement (classe java) différent.

Et bien c'est ce que nous allons faire immédiatement ! Je vous laisse créer 3 fragments très simples via l'assistant de création Android Studio : NewsPageFragment, ParamPageFragment et ProfilePageFragment.

Je vous en affiche un seul pour l'exemple, les deux autres seront strictement pareils (ils s'appelleront juste différemment bien sûr  ;) ).

Fichier NewsPageFragment.java :

public class NewsPageFragment extends Fragment {

    public static NewsPageFragment newInstance() {
        return (new NewsPageFragment());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_page_news, container, false);
    }
}

Explications : Nous allons reprendre la convention de création d'un fragment, en créant pour chacun des fragments une méthode publique statique newInstance( )

Fichier fragment_page_news.xml :

<LinearLayout
    android:id="@+id/fragment_page_news_rootview"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.openclassrooms.myamazingviewpager.Controllers.Fragments.NewsPageFragment"
    android:gravity="center"
    android:background="#EDD9CF">

    <TextView
        android:id="@+id/fragment_page_news_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="20dip"
        android:textSize="25sp"
        android:textStyle="bold"
        android:textColor="#fff"
        android:textAlignment="center"
        android:text="Nous pourrions afficher un fil d'actualité ici non ?"/>

</LinearLayout>

Explications : Comme vous pouvez le constater, j'ai modifié directement le texte dans le layout, ainsi que la couleur du fond. Et oui ! Chaque fragment est indépendant et possède donc son propre layout maintenant... ;)

Je vous laisse donc créer les deux autres fragments ainsi que les deux layouts associés.

                            

Une fois cela terminé, nous allons devoir modifier et simplifier notre adapter PageAdapter afin de lui dire d'afficher :

  • En page numéro 1 le fragment NewsPageFragment

  • En page numéro 2 le fragment ProfilePageFragment

  • En page numéro 3 le fragment ParamPageFragment

Fichier PageAdapter.java :

public class PageAdapter extends FragmentPagerAdapter {


    //Default Constructor
    public PageAdapter(FragmentManager mgr) {
        super(mgr);
    }

    @Override
    public int getCount() {
        return(3);
    }

    @Override
    public Fragment getItem(int position) {
        switch (position){
            case 0: //Page number 1
                return NewsPageFragment.newInstance();
            case 1: //Page number 2
                return ProfilePageFragment.newInstance();
            case 2: //Page number 3
                return ParamPageFragment.newInstance();
            default:
                return null;
        }
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position){
            case 0: //Page number 1
                return "Fil d'actualité";
            case 1: //Page number 2
                return "Profil";
            case 2: //Page number 3
                return "Paramètre";
            default:
                return null;
        }
    }
}

Explications : Notre adapter semble plus léger : il n'affichera maintenant que 3 fragments (ceux que l'on a créés précédemment), définis en fonction de la position en cours.

Extrait du fichier MainActivity.java 

public class MainActivity extends AppCompatActivity {

    ...
    
    private void configureViewPagerAndTabs(){
        
        ...
        
        //Set Adapter PageAdapter and glue it together
        pager.setAdapter(new PageAdapter(getSupportFragmentManager()));

        ...
    }
}

Lancez maintenant votre application : votre ViewPager affiche maintenant 3 fragments totalement indépendants ! Libre à vous d'y implémenter à l'intérieur ce que vous souhaitez.

J'espère que le résultat est à votre goût et que vous avez compris l'enchaînement et la logique de ces différents patterns.

                         

Conclusion

Encore bravo ! Nous avons créé ensemble une application, MyAmazingViewPager, implémentant un ViewPager ainsi qu'unTabLayout, affichant 3 fragments indépendants les uns des autres. Wouah !

Dans les prochains chapitres, nous irons encore plus loin en développant notre premier menu NavigationDrawer.

L'application terminée de ce chapitre se trouve à ce lien.

Exemple de certificat de réussite
Exemple de certificat de réussite