• 8 heures
  • Facile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 04/09/2023

Créez un second fragment et naviguez vers celui-ci

 

Dans la première partie de ce cours, nous avons créé un premier fragment correspondant à l’écran d’accueil de notre application, et permettant de récupérer le nom de l'utilisateur et de démarrer le jeu. Dans cette deuxième partie, nous allons créer un second fragment. Ce fragment permettra d'afficher le contenu du quiz. Il sera démarré par le premier fragment lorsque l'utilisateur cliquera sur le bouton de lancement du quiz.

Vous vous demandez sûrement comment fonctionne le quiz ?

C'est très simple : SuperQuiz va poser une série de quatre questions à l'utilisateur, choisies aléatoirement dans une banque de plusieurs questions. Pour chaque question, il aura le choix entre quatre réponses possibles. Lorsque l’utilisateur cliquera sur une réponse, le bouton changera de couleur de fond selon que la réponse est correcte ou non, et un message complémentaire s’affichera en bas, indiquant de manière textuelle si la réponse est bonne ou non. Enfin, un bouton apparaît également en bas pour permettre à l’utilisateur de passer à la question suivante. Cela donne par exemple la maquette suivante :

À gauche, l'écran contient la question et toutes les réponses. À droite, si l'utilisateur choisi la bonne réponse, le bouton de celle-ci change de couleur et un message
Maquette du fragment QuizFragment illustrant l’affichage d’une question et des 4 réponses, et l’évolution de cet écran lorsque l’utilisateur clique sur la bonne réponse

Configurez un nouveau fragment

Créez les fichiers

Pour rappel, un fragment est composé d'une classe Java et d’un fichier layout XML. Positionnez-vous dans l'arborescence de votre projet, au niveau du répertoire dans lequel est contenue la classe WelcomeFragment  créée précédemment. Faites un clic droit dessus, puis sélectionnez l'option New > Fragment > Fragment (Blank).

Dans l'arborescence, allez dans New > Fragment > Fragment Blank pour créer votre fichier layout
Créez un nouveau Fragment

Une nouvelle fenêtre s'affiche, vous permettant de configurer le nom du fragment et de son fichier layout. Sachant que ce fragment va gérer l’affichage du quiz, nous allons l’appeler QuizFragment  . Le nom du fichier layout associé doit être fragment_quiz  . Cliquez sur le bouton Finish.

Ajoutez les noms du fragment, QuizFragment, et de son layout, fragment_quiz
Configurez le nom du fragment et de son fichier layout

Ouvrez maintenant la classe QuizFragment  fraîchement créée par Android Studio. Par défaut, Android Studio propose un squelette de fragment recevant des paramètres en entrée. Dans notre cas, ça n’est pas utile. Un petit nettoyage s’impose. Vous pouvez supprimer le code chargé de maintenir et de gérer ces arguments. Vous devriez à la fin avoir une classe QuizFragment  semblable au code ci-dessous :

public class QuizFragment extends Fragment {

    public static QuizFragment newInstance() {
        QuizFragment fragment = new QuizFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                    Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_quiz, container, false);
    }
}

Créez le layout

L'interface de ce nouveau fragment va contenir les éléments suivants :

  • l'intitulé de la question posée à l'utilisateur ;

  • les quatre réponses possibles, chacune représentée par un bouton.

Ensuite, dès que l’utilisateur aura sélectionné une réponse, les éléments suivants apparaîtront :

  • un texte indiquant si la réponse est correcte ou non ;

  • un bouton permettant de passer à la question suivante ou de terminer le quiz.

Pour réaliser ce layout, ouvrez le fichier fragment_quiz.xml  situé dans le répertoire res/layout. Avant de commencer, oublions un instant que le texte et le bouton “Next” ne s’affichent que sous certaines conditions, car ces conditions d’affichage seront gérées dans le code Java du fragment.

La première question que vous devez vous poser avant de coder est : quel type de conteneur utiliser ? Puis quels composants utiliser pour représenter les éléments à l’écran, et avec quels attributs pour obtenir le rendu de la maquette précédente ?

Essayez par vous-même, puis rendez-vous ensuite ci-dessous pour la correction.

Dans notre cas, nous devons utiliser deux LinearLayout  imbriqués. Le premier avec une orientation verticale et le second, horizontale. Nous utiliserons les composants TextView et Button. Vous pouvez modifier le code comme suit :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   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"
   android:orientation="vertical"
   android:background="@color/white"
   android:gravity="center_horizontal">

   <TextView
       android:id="@+id/question"
       android:layout_width="match_parent"
       android:layout_height="0dp"
       android:layout_margin="16dp"
       android:padding="4dp"
       android:layout_weight="2"
       android:background="#767573"
       android:gravity="center"
       android:textColor="@color/white"
       android:textSize="18sp"
       android:textStyle="bold"
       tools:text="Question ?" />

   <Button
       android:id="@+id/answer1"
       android:layout_width="wrap_content"
       android:layout_height="0dp"
       android:layout_weight="1"
       android:layout_margin="4dp"
       android:paddingVertical="16dp"
       android:paddingHorizontal="32dp"
       android:textSize="20sp"
       android:textColor="@color/white"
       android:backgroundTint="#6200EE"
       tools:text="Answer1" />

   <Button
       android:id="@+id/answer2"
       android:layout_width="wrap_content"
       android:layout_height="0dp"
       android:layout_weight="1"
       android:layout_margin="4dp"
       android:paddingVertical="16dp"
       android:paddingHorizontal="32dp"
       android:textSize="20sp"
       android:textColor="@color/white"
       android:backgroundTint="#6200EE"
       tools:text="Answer2" />

   <Button
       android:id="@+id/answer3"
       android:layout_width="wrap_content"
       android:layout_height="0dp"
       android:layout_weight="1"
       android:layout_margin="4dp"
       android:paddingVertical="16dp"
       android:paddingHorizontal="32dp"
       android:textSize="20sp"
       android:textColor="@color/white"
       android:backgroundTint="#6200EE"
       tools:text="Answer3" />

   <Button
       android:id="@+id/answer4"
       android:layout_width="wrap_content"
       android:layout_height="0dp"
       android:layout_weight="1"
       android:layout_margin="4dp"
       android:paddingVertical="16dp"
       android:paddingHorizontal="32dp"
       android:textSize="20sp"
       android:textColor="@color/white"
       android:backgroundTint="#6200EE"
       tools:text="Answer4" />

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="0dp"
       android:layout_weight="1"
       android:orientation="horizontal"
       android:gravity="center">

       <TextView
           android:id="@+id/validityText"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:textColor="@color/black"
           android:layout_margin="8dp"
           android:padding="16dp"
           android:textSize="18sp"
           tools:text="💪 Good Answer !"
           android:textAlignment="textEnd"
           android:visibility="invisible"
           tools:visibility="visible"/>
       <Button
           android:id="@+id/next"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:backgroundTint="#767573"
           android:layout_margin="8dp"
           android:padding="16dp"
           android:textSize="18sp"
           android:text="Next"
           android:visibility="invisible"
           tools:visibility="visible"/>
   </LinearLayout>

</LinearLayout>

Vous devez déjà être familier avec certains attributs, tels que les marges, le texte à afficher ou les identifiants assignés aux éléments. Notez bien que les identifiants sont essentiels, ce sont eux qui permettront de référencer les éléments depuis le code, et de les mettre à jour dynamiquement. Néanmoins, d'autres attributs doivent vous interpeller.

L'attribut android:textColor  permet de spécifier quelle couleur utiliser pour la police d’écriture, pour un champ texte ou un bouton.

L'attribut android:background  prend le même paramètre que textColor  , mais permet pour sa part de préciser la couleur d'arrière-plan de la majorité des éléments (bouton, champ texte, layout, etc.).

L'attribut android:textStyle  permet de préciser le style à utiliser pour une police. Vous avez le choix entre bold  (gras), italic  (italique) ou normal  , la valeur par défaut.

L’attribut android:visibility  permet d’indiquer si un élément est visible ou non. Il y a trois valeurs possibles pour ce paramètre : visible  invisible  ou gone  . La différence entre invisible  et gone  est que dans le cas de “invisible”, l’élément est masqué, mais il occupe tout de même à l’écran l’espace qui lui était alloué. Alors que pour gone  , l’élément est également masqué mais il n’occupe pas d’espace à l’écran (c’est comme si sa largeur et sa hauteur devenaient nulles).

Vous constatez peut-être au sein des attributs la présence d’un nouveau préfixe, tools  . Par exemple, tools:text  et tools:visibility  . Il permet dans ce cas d’usage de personnaliser un attribut uniquement pour la prévisualisation qui en est faite dans Android Studio. C’est très pratique pour développer.

Enfin, le dernier attribut très important est android:layout_weight  . C'est un attribut spécifique aux enfants d'un LinearLayout  . Il permet de préciser le poids d'un élément par rapport aux autres. Je m'explique. Si vous assignez un poids identique pour tous les éléments (par exemple 1), tous ces éléments auront la même taille. Si vous assignez un poids égal à 2 à l'un des éléments, alors sa taille sera deux fois plus importante que celle des autres. Essayez de faire varier le poids des éléments du code ci-dessus, afin de voir le résultat. N'hésitez pas à consulter cette page pour avoir une explication plus détaillée.

Le résultat produit doit être similaire à la capture ci-dessous. Amusez-vous à modifier les différents attributs pour donner un style qui vous est propre !

Capture d’écran de la prévisualisation de l'interface correspondant au code et à la description précédents.
Prévisualisation de l’interface du fragment de quiz que vous devriez obtenir

Lancez le nouveau fragment

C'est bien beau tout ça, mais comment afficher ce nouveau fragment ?

Rappelez-vous : nous avions commencé à implémenter la méthode onClick  dans la classe WelcomeFragment  . Cette méthode est appelée à chaque fois que l'utilisateur appuie sur le bouton. Et c'est à cet endroit précis que nous allons démarrer notre nouveau fragment.

Pour démarrer un nouveau fragment, Android met à disposition le FragmentManager  . Cette classe permet d’ajouter, de supprimer ou de remplacer un fragment au sein d’un hôte donné. Elle s’occupe également de gérer la pile "Retour" associée. Pour accéder au FragmentManager depuis un fragment, il faut appeler la méthode getParentFragmentManager()  .

Le fait de pouvoir ajouter, supprimer, remplacer un fragment suite à une action de l’utilisateur s’appelle une transaction. Dans notre cas, pour pouvoir afficher le nouveau fragment QuizFragment, il faut donc démarrer une transaction grâce à la fonction beginTransaction()  , puis créer un objet de type QuizFragment  , et enfin ajouter ce dernier fragment au sein de l’hôte prévu à cet effet, via l’objet de type transaction obtenu précédemment avec la fonction beginTransaction()  . Dans notre cas, l’hôte qui va accueillir nos différents fragments est le conteneur FrameLayout  portant l’identifiant “container” au sein de l’activité principale de notre application. Voici le code correspondant à ces explications :

FragmentManager fragmentManager = getParentFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
QuizFragment quizFragment = QuizFragment.newInstance();
fragmentTransaction.add(R.id.container, quizFragment);
fragmentTransaction.commit();

Ajoutez ces cinq lignes de code dans la méthode onClick  . Puis lancez l'application, cliquez sur le bouton, et vous devriez voir apparaître le nouveau fragment. 

À noter que pour que l’utilisateur puisse retourner sur l’écran d’accueil en naviguant en arrière depuis le fragment de quiz, il faut ajouter la ligne de code suivante : fragmentTransaction.addToBackStack(null);  juste avant fragmentTransaction.commit();  . Dans notre cas, nous ne souhaitons pas qu’il puisse retourner à l’écran d’accueil une fois que le jeu a démarré, donc rien à faire.

Récapitulons en vidéo

Retrouvez ces différentes étapes dans la vidéo ci-dessous :

En résumé

  • Pour créer un nouveau fragment dans un projet, il faut créer la classe Java et le layout XML associé.

  • Pour naviguer vers ce fragment, il faut utiliser le FragmentManager  . 

  • Le FragmentManager  permet de définir quel fragment ajouter, supprimer ou remplacer, via une transaction.

Votre deuxième fragment est maintenant créé. Bravo !

Avant de passer au quiz, ouvrons une parenthèse purement théorique afin de comprendre à quoi correspondent les fonctions onCreate  , onCreateView  et onViewCreated  , que nous avons manipulées jusqu'ici sans trop savoir à quoi elles correspondent.

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