Layouts

Construction dynamique et statique des écrans Android

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

On commencera notre série d'articles pratiques sur le développement sous Android par la présentation de la couche vue. On verra ici comment définir un layout dans le fichier XML et directement dans le code. Ensuite on abordera l'aspect des View.

Qu'est-ce que c'est Layout sous Android ?

Layout, comme son nom indique, est une représentation visuelle de l'application Android. Elle peut contenir du texte, des images, des formulaires et peut intéragir avec l'utilisateur. Les layouts peuvent être construits à partir d'un fichier XML ou directement dans le code Java, au moment d'exécution de l'application.

Les éléments du layout sont identifiables grâce à l'attribut id. Cela permet de les manipuler dans la couche d'action, par exemple dans l'activité, comme dans l'exemple ci-dessous :

<EditText
            android:id="@+id/mailTitle"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
        /> 
final EditText title = (EditText) findViewById(R.id.mailTitle);

A part l'attribut id, on remarque également la présence des attributs précédés par le mot layout_. Il s'agit d'éléments propres aux layouts. Les attributs le plus souvent utilisés sont la largeur (layout_width) et la hauteur (layout_height). Le premier peut prendre comme attribut :
- fill_parent : prend la même largueur que son conteneur (l'élément dans lequel il est placé)
- wrap_content : prend la largeur réel de l'élément.

Attention, depuis la version 8 de l'API, le paramètre fill_parent a été remplacé avec match_parent. Les mêmes valeurs s'appliquent à l'attribut layout_height. layout_width et layout_height peuvent aussi prendre les valeurs numériques (34dp par exemple).

Voici d'autres attributs qu'on utilisera dans notre application :

    <LinearLayout  
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" 
     >

android:orientation : soit vertical, soit horizontal, indique l'orientation d'un élément.

<TextView
        android:id="@+id/prefRefererUriLabel"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/pref_ref_uri" />

android:text : renseigne le contenu d'un block avec le texte.

    <EditText
        android:id="@+id/prefAbout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="textMultiLine"
    />

android:inputType : détermine le type de l'EditText à afficher.

<Spinner
        android:id="@+id/prefNotifFrequency"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:entries="@array/frequency_list"
     />

android:entries : une liste des possibilités que peut choisir l'utilisateur dans une liste déroulante. @array indique qu'il s'agit d'une ressource stockant des tableaux.

        <Button
            android:id="@+id/prefButtonSubmit"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/pref_btn_submit"
            android:onClick="handleForm"
        />

android:onClick : une méthode de l'activité qui sera appelée après le click sur l'élément.

   	<AutoCompleteTextView 
   		android:id="@+id/autocompleteContactList" 
   		android:layout_width="fill_parent"
   		android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@id/labelSmsNumber"
   		android:layout_marginRight="5dip"
   		android:layout_marginTop="10dip"
   		android:layout_marginLeft="5dip"  />

android:layout_alignParentLeft : détermine si l'élément doit être placé à gauche d'un autre élément.

android:layout_below : dans le layout relatif (RelativeLayout), il indique après quel élément doit être positionné l'élément portant cet attribut

android:layout_marginRight : (et layout_marginLeft, layout_marginTop, layout_marginBottom) indique la marge à appliquer à l'élément.

    <Button 
        android:id="@+id/buttonBooks"
        android:layout_width="150dp"
        android:layout_height="75dp" 
        android:layout_alignParentRight="true"
        android:layout_below="@id/mainWelcomeText"
        android:text="@string/label_books"
        android:onClick="goToBooksList"
    />

android:layout_alignParentRight : détermine si l'élément doit être placé à droite d'un autre élément.

    <Button
        android:id="@+id/backToMain"
        android:layout_width="wrap_content"
        android:layout_height="75dp"
        android:onClick="goToMainActivity"
        android:text="@string/website_back_label"
        android:visibility="invisible"
        tools:ignore="OnClick" />

android:visibility : soit invisible (pas visible), soit visible, cet attribut spécifie si un élément doit être affiché à l'écran.

        <com.example.library.view.PlacementTextView 
            android:id="@+id/customizeActionsContainer"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/black_bottom_border"
            android:layout_marginTop="4dp"
            />

android:background : spécifié quelle image de fond doit être appliquée à l'élément.

Des types de layouts sous Android

De différents types des layouts existent sous Android. On abordera ici ceux qui seront présents dans notre exemple d'application Android :
- LinearLayout : les éléments sont placés d'une manière linéaire, soit verticalement, soit horizontalement (soit en lignes, soint en colonnes)
- RelativeLayout : permet de placer les éléments d'une manière relative. C'est-à-dire que les éléments peuvent positionnés les uns par rapport aux autres. On l'a vu dans l'article précédent où les attributs layout_below, layout_alignParentRight et layout_alignParentLeft indiquent quel élémenet doit être placé derrière un autre.
- FrameLayout : permet d'afficher une unique vue. On peut grouper les éléments qui doivent y être affichés. Une bonne pratique est cependant de ne pas grouper les vues car cela peut poser les problèmes lors de l'affichage de l'application sur les écrans différents. Il ressemble à RelativeLayout car avec l'attribut android:layout_gravity on peut contrôler l'affichage des éléments. Il ne permet pas néanmoins de gérer les dépendances d'affichage et dire par exemple, qu'un élément doit être affiché derrière un autre etc.
- ListView : représente l'affichage d'une liste.
- WebView : représente l'affichage d'une page web avec l'interprétation des balises HTML.
- ScrollView : représente l'affichage d'un écran avec un scroll. Seul le scroll vertical est accepté. Pour le scroll horizontal, il faut utiliser HorizontalScrollView. Il est important de ne placer qu'un seul élémenent dans ScrollView.

View sous Android

Tous les éléments qui peuvent apparaître sur l'écran sont représentés par les instances héritant de la classe View. Il s'agit donc des carrés qui rendent visible un élément et qui peuvent intercepter le comportement de l'utilisateur (click, sélection...).

On a déjà vu dans cet article une méthode findViewById(). C'est elle qui se charge de retrouver un élément d'après l'identifiant qui lui est attribué. Elle retourne l'instance View qui ensuite doit être castée en élément souhaité.

Voici une liste des éléments dont les classes héritent de View et qui seront utilisés dans notre application :
- TextView : l'élément qui contient le texte.
- EditText : l'élément qui permet d'écrire le texte. Il ressemble à <input type="text" /> en HTML.
- RadioGroup avec RadioButton : un groupe de boutons radio, composé d'éléments <RadioBouton />.
- DatePicker : l'élément qui représente le calendrier utilisé pour sélectionner un date.
- Spinner : comparé à l'HTML, cet élément ressemble à la liste déroulante <select />
- Button : un bouton qu'on peut utiliser pour, par exemple, inciter l'utilisateur a effectuer une action ou indiquer à l'utilisateur l'élément utilisé pour soumettre un formulaire.
- AutoCompleteTextView : l'élément aidant à créer les listes auto-complete (suggéstion automatique)
- TabHost : un conteneur utilisé dans l'affichage des onglets. Il contient deux composants : un avec les onglets, l'autre avec le contenu correspondant à l'onglet sélectionné.
- com.example.library.view.PlacementTextView : une classe héritant du TextView qui aura pour but de faciliter l'implémentation du glissé-deposé. On verra cela plus en détail dans la partie consacrée à l'utilisation du drag&drop sous Android.

GroupView sous Android

Pendant la description du RadioGroup, on a vu qu'il contenait plusieurs éléments du type RadioButton. Dans cette situation on ne parle pas du View, mais du ViewGroup. ViewGroup est donc un conteneur capable de stocker plusieurs views. Cependant ViewGroup hérite également de la classe View.

Les layouts (RelativeLayout, LinearLayout, FrameLayout, TableLayout) font également partie des ViewGroup.

Définir un layout à l'exécution de l'application

Jusque là on a vu la définition des layouts via les fichiers XML. Dans cette méthode, les layouts doivent être définis en avance, avant le lancement de l'application. Mais on a déjà mentionné qu'il existait une autre méthode.

Cette autre méthode est exécutée au moment où l'application est lancée. Elle garantit une bonne fléxibilité de layouts mais est plus complexe à mettre en place et peut donc provoquer plus de bugs de l'application. La définition d'un affichage selon cette méthode se base sur la création des views via leurs constructeurs. Le groupage se fait grâce à la méthode addView(newElement) qui ajoute un élément (paramètre newElement) à l'élément qui effectue l'appel de cette fonction. Regardons cela sur un exemple de notre application :

afficher le code

Dans le code ci-dessus on voit qu'un LinearLayout (container) est créé. Il joue le rôle d'un conteneur. Ensuite on initialise un TextView (header) qui contient le nom du livre et qui réagit au click. Plus loin on associe le TextView à notre conteneur qui à son tour est attaché à la classe OneBookView. Le dernier attachement est possible car la classe OneBookView hérite de LinearLayout et donc peut invoquer la méthode addView.

TODO : présenter TableLayout

TODO : présenter LayoutInflater

Bartosz KONIECZNY Vues et layouts

Une question ? Une remarque ?

*

*

Un conseil PHP

Fonctions dynamiques.

PHP permet de construire des fonctions à partir des variables. On peut très simplement construire une méthode dynamique qui génère une image en fonction du type de fichier transféré :

// filename has only alphanumerical caracters
$names = explode('.', $_FILES['image1']['name']);
$fname = "imagecreatefrom".$names[1];
$fname('fileOne');