Pages

dimanche 11 novembre 2012

Utiliser les fragments dans une application Android

Les fragments ont été introduits avec la version 3.0 d’Android (Honeycomb API level 11) pour faciliter le portage des applications sur les différentes tailles d’écran.


Pour simplifier un fragment peut être vu comme une partie de l’interface utilisateur que l’on souhaite réutiliser dans plusieurs activités ou disposer différemment en fonction de la taille des écrans des devices.


Un fragment a son propre cycle de vie. Il reçoit ses propres événements d'entrée, et il peut être ajouté ou supprimé alors que l'activité est en cours d'exécution. Par contre son cycle de vie est directement lié à celui de l’activité qui l’a lancé. Par exemple quand une activité est en pause, tous ses fragments sont mis en pause. Il en est de même lors de la fermeture. Comme lorsque l’on navigue d’une activité à une autre, vous pouvez choisir d’ajouter le fragment sur la back stack pour que le fragment soit réaffiché lorsque l’utilisateur clique sur le bouton retour.

Un fragment est ajouté au layout de l’activité dans un élément ViewGroup soit directement dans le fichier xml (via le tag <fragment) soit dans le code Java de l’activité


Création d’un fragment 
Pour écrire un fragment, vous devez écrire une classe héritant de Fragment. Comme pour les activités vous pouvez surcharger différentes méthodes pour agir sur le fragment tout au long de son cycle de vie

Généralement un fragment implémentera les méthodes suivantes
  • onCreate(Bundle) pour initialiser les différents composants 
  • onCreateView(LayoutInflater, ViewGroup, Bundle) appelé lorsque l’interface est créée la première fois. Cette méthode permet de renvoyer la vue associée au fragment à l’activité 
  • onPause() pour persister les modifications utilisateurs pour qu’il puisse les retrouver lorsque le fragment sera à nouveau actif.

Un exemple d’utilisation 
Comme exemple nous allons mettre en place une activité présentant un menu sous forme d’onglet qui permettra à chaque clic d’afficher un fragment différent.

Dans notre exemple les fragments auront tous la même structure affichant seulement un message indiquant qui ils sont, et une image


<RelativeLayout 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" > 

     <TextView 
            android:id="@+id/fragment1" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:layout_centerInParent="true" 
            android:text="@string/fragment3_desc" /> 
    <ImageView
            android:id="@+id/imageView1" 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:layout_below="@+id/fragment1" 
            android:layout_centerHorizontal="true" 
            android:layout_marginTop="39dp" 
            android:src="@drawable/javamind" /> 
</RelativeLayout>


Au niveau du layout principal nous allons déclarer un conteneur que nous allons utiliser programmativement pour lui insérer les fragments

<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" 
      >    

  <TextView 
            android:id="@+id/hello"           
            android:layout_width="wrap_content"            
            android:layout_height="wrap_content"            
            android:text="@string/hello"            
            android:textAppearance="?android:attr/textAppearanceMedium" /> 

  <LinearLayout            
            android:id="@+id/fragmentContainer"            
            android:layout_width="match_parent"            
            android:layout_height="match_parent" >   
  </LinearLayout> 
</LinearLayout>

Au niveau du fragment, nous devons, comme indiqué un plus haut dans cet article, surcharger la méthode onCreateView pour renvoyer le fragment à l’Activity. Nous en profitons pour faire une méthode générique en ajoutant deux paramètres nom et id


public class ExempleFragment extends Fragment { 
    private String name; 
    private int id;     

        public ExempleFragment(String name, int id) { 
        super();         
                this.name = name;
        this.id = id;
    }
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
                Bundle savedInstanceState) { 
    
        // Inflate the layout for this fragment 
        return inflater.inflate( 

        getResources().getIdentifier("fragment" + id, "layout",
         container.getContext().getPackageName()), container, false); 
    }     

        public String getName() { 
        return name;
    } 
} 
}

Il ne reste plus qu’à gérer l’activité

public class MainActivity extends Activity implements TabListener { 

   private ExempleFragment frag1 = new ExempleFragment("Fragment 1", 1);
   private ExempleFragment frag2 = new ExempleFragment("Fragment 2", 2); 
   private ExempleFragment frag3 = new ExempleFragment("Fragment 3", 3); 
   

   @Override
   public void onCreate(Bundle savedInstanceState) {       
      super.onCreate(savedInstanceState);             
      getWindow().requestFeature(Window.FEATURE_ACTION_BAR);       
      setContentView(R.layout.activity_main); 
 
      //Configuration de la barre d'onglet       
      getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);       
      getActionBar().addTab(getActionBar()
         .newTab().setText(frag1.getName()).setTabListener(this));         
      getActionBar().addTab(getActionBar() 
         .newTab().setText(frag2.getName()).setTabListener(this));  
      getActionBar().addTab(getActionBar() 
         .newTab().setText(frag3.getName()).setTabListener(this));  
   } 
   
   @Override 
   public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
      Toast.makeText(this, tab.getText() + " selected", 
         Toast.LENGTH_SHORT).show();       

      if(tab.getText().equals(frag1.getName())){              
         ft.replace(R.id.fragmentContainer, frag1);
      }
      else if(tab.getText().equals(frag2.getName())){
         ft.replace(R.id.fragmentContainer, frag2);
      }
      else if(tab.getText().equals(frag3.getName())){ 
         ft.replace(R.id.fragmentContainer, frag3);
      }
   } 

   @Override
   public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
      Toast.makeText(this, tab.getText() + " unselected", 
         Toast.LENGTH_SHORT).show();       

      if(tab.getText().equals(frag1.getName())){
         ft.remove(frag1);
      }
      else if(tab.getText().equals(frag2.getName())){
         ft.remove(frag2);
      }
      else if(tab.getText().equals(frag3.getName())){
         ft.remove(frag3);
      }
   } 

   @Override
   public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
      Toast.makeText(this, tab.getText() + " unselected", 
            Toast.LENGTH_SHORT).show();
   }
}

Maintenant vous n’avez plus qu’à lancer l’application
 

Vous pouvez récupérer les sources de cet exemple sur github à l’adresse suivante https://github.com/javamind/annexe/tree/master/FragmentExamples

Un autre article sur l'interaction entre les fragments est disponible ici

Aucun commentaire:

Enregistrer un commentaire

Remarque : Seul un membre de ce blog est autorisé à enregistrer un commentaire.