Introduits à partir de d’ANDROID 3.0 (API 11), les fragments permettent de développer des applications qui offriraient une navigation adaptée aussi bien à l’utilisation à partir d’un téléphone portable qu’à partir d’une tablette.
Ci-dessous une figure exposant l’apport des fragments. Avec cette technique il est possible d’avoir une vue par écran sur les Smartphones et deux sur les tablettes.
Et parce que rien ne vaut un exemple, on réalisera ensemble et pas à pas une petite application météo. Cette application devra afficher une liste de pays. Le clic sur un élément de la liste, affichera les prévisions météo du pays en question.
Nous allons la développer de sorte que sur un téléphone on aura la liste des pays sur tout l’écran, et le clic sur un élément démarrera une nouvelle activité qui affichera les prévisions météo. Du moment que sur une tablette, on aura la liste des pays et les prévisions sur le même écran. Le clic sur un pays mettra à jour les prévisions.
Pour résumer, nous aurons :
Retour à notre exemple.
Dans notre cas nous aurons deux fragments list_pays_fragment et prevision_fragment. Nous aurons également deux activités list_pays_activity et prevision_activity.
Le clic sur un pays, selon la taille de l’écran, démarrera l’activité et prevision_activity ou mettra directement à jour le fragment prevision_fragment. Donc list_pays_activity aura deux fichiers list_pays_activity.xml, l’un sous layout et l’autre sous layout-Large.
Commençons par créer les layouts.
Nous avons layout/list_pays_activity.xml qui devra afficher uniquement la liste des pays. Donc elle contiendra un seul fragment qui sera list_pays_fragment.
Nous avons layout-large/list_pays_activity.xml qui devra afficher la liste des pays et les prévisions. Donc elle contiendra deux fragments list_pays_fragment et prevision_fragment.
La liaison entre un fragment et la classe correspondante se fait par le biais de l’attribut class de la balise fragment. Ceci veut dire c’est la classe ListPaysFragment qui chargera le contenu de list_pays_fragment.xml dans ce fragment.
Sans oublier que nous avons layout-Large/list_pays_activity.xml qui devra afficher la liste des pays et les prévisions météo.
NB : Pour le reste du code source consultez le code source ici.
Passons maintenant aux classes, et commençons par les fragments.java.
ListPaysFragment.java
On commence par charger le contenu du fichier list_pays_fragment.xml dans le fragment.
Ensuite nous informons l’activité que nous souhaitons consulter les prévisions d’un pays donné. Pour pouvoir le faire nous allons devoir créer une interface OnPaysSelected qui sera implémentée par la classe de l’activité. Cette interface nous permettra d’appeler les méthodes qui y sont déclarées et qui ont été implémentées par l’activité.
Maintenant il ne reste plus qu’à attaché ce listner à notre activité pour pouvoir communiquer avec elle.
Il ne reste plus qu’à faire appel à la méthode paysSelect(String).
Passons maintenant à la chose la plus importante : comment savoir si l’on doit mettre à jour un fragment déjà à l’écran ou lancer une nouvelle activité ?
On commence par récupérer le fragment. Ensuite on vérifie s’il est déjà affiché ou pas.
J’ai essayé de commenter au mieux le code source. Si vous avez des questions n’hésitez pas à poster vos commentaires.
Pour résumer, nous aurons :
- Vue1 : Liste des pays
- Vue2 : Prévisions météo
- Chaque Vue est un Fragment qui dispose d’un fichier XML et d’une classe Java.
- Certaines Activités afficheront, selon la taille de l’écran, un ou deux fragments. Donc ces dernières disposeront de deux fichiers XML.
<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"
tools:context=".ListPaysActivity">
<fragment
android:id="@+id/list_pays_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.example.tutometeo.ListPaysFragment">
</fragment>
</LinearLayout>
|
<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"
tools:context=".ListPaysActivity">
<fragment
android:id="@+id/list_pays_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
class="com.example.tutometeo.ListPaysFragment">
</fragment>
<fragment
android:id="@+id/prevision_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
class="com.example.tutometeo.PrevisionFragment">
</fragment>
</LinearLayout>
|
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.list_pays_fragment,
container, false);
ListView listPays = (ListView) view.findViewById(R.id.list_pays);
listPays.setAdapter(new
ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, pays));
listPays.setOnItemClickListener(selectPays);
return view;
}
|
public interface OnPaysSelected {
/**
* @param name
*
Nom du pays sélectionné sur la liste.
*/
public void paysSelect(String name);
}
|
private OnPaysSelected paysFragListener;
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
paysFragListener = (OnPaysSelected) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " doit implementer OnPaysSelected ");
}
}
|
private OnItemClickListener selectPays = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
paysFragListener.paysSelect(pays[arg2]);
}
};
|
public void paysSelect(String region) {
//On récupère le fragment PrevisionFragment
PrevisionFragment fragment =
(PrevisionFragment) getSupportFragmentManager() .findFragmentById(R.id.prevision_fragment);
//Si le fragment est déjà à l'écran on le met à jour (tablette), si non on démarre
une nouvelle activité (Smartphone).
if ((fragment != null) && fragment.isInLayout()) {
fragment.setMsg("Prévision de " + region + " dans un fragment mis à jour");
} else {
Intent intent = new Intent(this, PrevisionActivity.class);
intent.putExtra(PrevisionActivity.MSG_EXTRAS, "Prévision de
" + region + " dans une nouvelle activité");
startActivity(intent);
}
}
|
Great! very usefull
RépondreSupprimerCe commentaire a été supprimé par l'auteur.
RépondreSupprimer