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.