IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants graphiques Android Discussion :

Adapter & Layout


Sujet :

Composants graphiques Android

  1. #1
    Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2011
    Messages : 47
    Points : 46
    Points
    46
    Par défaut Adapter & Layout
    Bonjour,

    Dans le cadre de mon appli android, j'essaye d'afficher le contenu d'un fichier. Pour l'instant, j'ai voulu m'entraîne en l'affichant sous forme d'une listView.


    J'arrive à parcourir mon arborescence, et je créé un Hashmap avec le nom, et le chemin du fichier.
    J'ai trouvé en cherchant sur le web une chose qui a l'air très sympa : les adapters. J'ai donc essayé d'en utiliser un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    HashMap<String, String> tampon;
    		if(fichiersMusique != null){
    			for(File fichier : fichiersMusique) {
    				//Si ce n'est pas un fichier caché et que c'est un fichier audio
    				if(!fichier.isHidden() && (new Fichier(fichier).estFichierAudio())){
    					tampon = new HashMap<String, String>();
     
    					tampon.put("Nom du fichier", fichier.getName());
    					tampon.put("Chemin du fichier", fichier.getAbsolutePath());
     
    					listeFichier.add(tampon);
    				}
    			}
     
    			if((listeFichier.size() < 1)){
    				Logs.affichage(MainActivity.getContexte(), "Vous n'avez pas de fichier musical !");
    			}else{
    				ListAdapter adapter = new SimpleAdapter(contexte,  
    					      //Valeurs à insérer
    						listeFichier, 
    					      /*
    					       * Layout de chaque élément (là, il s'agit d'un layout par défaut
    					       * pour avoir deux textes l'un au-dessus de l'autre, c'est pourquoi on 
    					       * n'affiche que le nom et le numéro d'une personne)
    					      */
    					      R.layout.listeview,
    					      /*
    					       * Les clés des informations à afficher pour chaque élément :
    					       *  - la valeur associée à la clé « text1 » sera la première information
    					       *  - la valeur associée à la clé « text2 » sera la seconde information
    					      */
    					      new String[] {"Nom du fichier", "Chemin du fichier"}, 
    					      /*
    					       * Enfin, les layouts à appliquer à chaque widget de notre élément
    					       * (ce sont des layouts fournis par défaut) :
    					       *  - la première information appliquera le layout « android.R.id.text1 »
    					       *  - la seconde information appliquera le layout « android.R.id.text2 »
    					      */ 
    					      new int[] {android.R.id.text1, android.R.id.text2 });
    					    //Pour finir, on donne à la ListView le SimpleAdapter
    						listView.setAdapter(adapter);
    			}
    		}
    Ne faites pas attention à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MainActivity.getContexte()
    , je sais que c'est vraiment crados, je corrige ça dès que j'aurai fini ce message

    Je sais que je peux utiliser un arrayAdapter, mais que j'utilise celui-ci ou le simpleAdapter, ma question est la même.


    Voici mon layout pour ma listView :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="?android:attr/listPreferredItemHeight"
        android:padding="6dip" >
     
        <TextView
            android:id="@+id/secondLine"
            android:layout_width="fill_parent"
            android:layout_height="26dip"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:ellipsize="marquee"
            android:singleLine="true"
            android:text="Description"
            android:textSize="12sp" />
     
        <TextView
            android:id="@+id/firstLine"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_above="@id/secondLine"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_alignWithParentIfMissing="true"
            android:gravity="center_vertical"
            android:text="Example application"
            android:textSize="16sp" />
     
     
    </RelativeLayout>

    En ce qui concerne les paramètres, je donne le contexte, les données, le layout de la listView ( j'ai créé un fichier XML avec le layout que je souhaite ), les clés dans le HashMap auxquelles vont correspondre les infos que je souhaite afficher, et le dernier paramètre, je ne le comprends pas.


    Le tuto que j'ai suivi ne détaille pas assez à mon goût ce "layout d'item". En effet, le code fonctionne avec la méthode qu'il donne sur le tuto, càd en utilisant les id de layout de base d'android, mais où placer mes propres layout de ligne ? Il ne correspondent pas à ceux que j'ai précisé dans mon fichier listView ? Je trouve ça un peut bizarre de devoir donner l'id d'un layout correspondant à la ligne que l'on veut afficher alors que plus haut on donne un layout à la listView ( et qu'on ne peut pas utiliser l'id des textview la composant par exemple .. )



    J'espère avoir réussi à être assez clair


    Merci d'avance,
    Julien

  2. #2
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par Synoyx Voir le message
    Le tuto que j'ai suivi ne détaille pas assez à mon goût ce "layout d'item". En effet, le code fonctionne avec la méthode qu'il donne sur le tuto, càd en utilisant les id de layout de base d'android, mais où placer mes propres layout de ligne ?
    c'est un paramètre de certains adapters. Regarde les bons tutoriels pour apprendre Android.
    Il ne correspondent pas à ceux que j'ai précisé dans mon fichier listView ?
    Quel fichier list-view ? une list-view n'est pas un fichier... tu parles du fichier de layout contenant la list-view ? Dans ce cas... c'est le layout contenant la list-view, en aucun cas le contenu de la list-view.
    Dans l'éditeur graphique il est possible d'avoir une "preview", mais c'est juste pour avoir une idée de l'UI finale, puisque c'est l'adapter qui fournit les views pour chaque item.

    Les adapters par défaut fournis dans le SDK sont tous basé sur un layout d'item unique, passé en paramètre au constructeur. Mais on peut très bien avoir des Adapters avec 20 layouts différents pour chaque type d'item.

    Je trouve ça un peut bizarre de devoir donner l'id d'un layout correspondant à la ligne que l'on veut afficher alors que plus haut on donne un layout à la listView ( et qu'on ne peut pas utiliser l'id des textview la composant par exemple .. )
    La je ne comprends pas... chaque item a ses propres id, et on peut donc y récupérer n'importe quel élément (textview ou autre)...
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  3. #3
    Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2011
    Messages : 47
    Points : 46
    Points
    46
    Par défaut
    Citation Envoyé par nicroman Voir le message
    c'est un paramètre de certains adapters.
    Après quelques réflexions, j'ai compris que ce paramètre sert en gros à dire à quelle colonne de mon hashmap va correspondre tel layout, c'est ça ?

    Citation Envoyé par nicroman Voir le message
    Quel fichier list-view ? une list-view n'est pas un fichier... tu parles du fichier de layout contenant la list-view ? Dans ce cas... c'est le layout contenant la list-view, en aucun cas le contenu de la list-view.
    Dans l'éditeur graphique il est possible d'avoir une "preview", mais c'est juste pour avoir une idée de l'UI finale, puisque c'est l'adapter qui fournit les views pour chaque item.
    Oui c'était bien le fichier XML de mon layout listView
    Par contre je viens de tester ce matin encore, l'éditeur graphique ne fonctionne pas pour ma part ( j'utilise eclipse + l'ADT ), il m'affiche juste une activité avec le logo de mon appli ...

    Citation Envoyé par nicroman Voir le message
    Les adapters par défaut fournis dans le SDK sont tous basé sur un layout d'item unique, passé en paramètre au constructeur. Mais on peut très bien avoir des Adapters avec 20 layouts différents pour chaque type d'item.
    Je n'ai pas tous compris là Quand tu dis "20 layouts différents / item", que veux tu dire ? Le layout change selon la situation par exemple ?


    Citation Envoyé par nicroman Voir le message
    La je ne comprends pas... chaque item a ses propres id, et on peut donc y récupérer n'importe quel élément (textview ou autre)...
    Moi non plus je n'ai pas compris Je pensais qu'en gros je pouvais récupérer des composants de mon layout qui possèdent un ID ( ici les textview de mon layout listView ), mais Eclipse me mettait constamment en erreur ... J'ai essayé de le redémarrer plusieurs fois, j'ai même eu un bug ADB, impossible de redémarrer une machine android, j'ai redémarré mon ordi plusieurs fois et à la fin il ne me mettait plus en erreur ... Est-ce dû à mon ordinateur ou à Eclipse ? En tout cas je commence à regarder d'autres IDE pour android, si tu en a un de sympa à me proposer .. ( Bien sûr, j'ai vu le post "http://www.developpez.net/forums/d1070841/java/general-java/java-mobiles/android/ide-developpement-android/" et intelliJ IDEA m'a l'air sympa, je l'ai essayé mais suis un peu déstabilisé de part la différence avec Eclipse que j'ai utilise pendant 3 bonnes années pour d'autres langages, j'ai peur de payer le logiciel et de ne pas l'utiliser après )



    Merci pour tes réponses en tout cas, tu es toujours présent pour sauver les newbies en détresse

    Julien

  4. #4
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Je vais essayer de faire plus simple....

    Un "layout" est juste un fichier XML que le framework android est capable de transformer en objets (les views), correctement positionnés.


    Une "View" (ListView, Button, EditText, TextView, ImageView...) sont les éléments graphiques de bases (certains appellent celà des widgets, mais dans le monde Android on risque de les confondre avec les "app-widgets", d'ou le terme préféré de "view"). Aucune view ne peut avoir de "layout" puisque la view est justement le composant créé par la lecture d'un layout.
    D'où mon incompréhension:
    Oui c'était bien le fichier XML de mon layout listView
    Pour moi veut dire le layout de la ListView... mais ce n'est pas possible. Donc je pense qu'on parle du layout fourni à l'activité (setContentView), et qui *contient* une ListView.

    Ensuite, la ListView est un élément relativement simple (relativement parce qu'il y a un boulot de "cache" assez énorme): elle utilise un "ListAdapter" pour récupérer des items. Ces items sont just des données (j'y reviendrai plus loin).
    Pour chaque item à afficher, la ListView va demander à l'adapter la "View" qui correspond à l'item (fonction getView()).
    L'adapter est libre de renvoyer ce qu'il veut...

    Les adapters "simples" (et en particulier SimpleAdapter) renvoient toujours le même type de view... et cette view est crée à partir d'un layout passé en paramètre du constructeur (le parametre resource de SimpleAdapter). C'est donc le layout correspondant aux items.

    Toujours dans le cas de SimpleAdapter (qui est fort simpliste), chaque item est une HashMap. Et on passe même une correspondance entre les identifiants des views de ce layout des items, et les clés de cette map de valeurs.
    Il est bien évidant que c'est la porte ouverte aux erreurs (perte de typage des données, difficultés de trouver des erreurs en particulier de valeur "null", etc...).

    C'est pourquoi je recommande plutôt d'utiliser des ArrayAdapter<MonTypeDeDonnee> avec MonTypeDeDonnee une classe maîtrisée avec des valeurs fortement typées.
    L'utilisation est très simple, puisqu'il suffit de surcharger la fonction getView() de l'adapter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    class MonAdapterDeMonType extends ArrayAdapter<MonTypeDeDonnee>
    {
         public MonAdapterDeMonType(Context ctxt, MonTypeDeDonnee[] array)
         {
               super(ctxt,R.layout.typeItemLayout,array);
         }
     
         public View getView(int position, View convertView, ViewGroup parent)
         {
              View ret = super.getView(position,convertView,parent);
              MonTypeDeDonnee item = getItem(position);
     
              TextView text = (TextView) ret.findViewById(R.id.text);
              ImageView img = (ImageView) ret.findViewById(R.id.image);
              text.setText(item.getText());
              img.setImageFromResource(item.getImageResource());
     
              return ret;
         }
    }
    Il existe diverses optimisations de ce code (les "handlers") mais si le layout inital ne contient pas 20 éléments la différence ne sera pas flagrante.


    Et pour finir sur les "multiple" layout... Le getView() peut à priori renvoyer ce qu'il veut... Mais l'interêt est d'utiliser le "cache" de ListView (convertView de la fonction getView()) quand il est disponible. Pour cela, l'Adapter indique pour chaque item à la ListView de quel type il est ( fonction getItemViewType() ). Ce qui permet à la ListView de conserver un cache en fonction des types d'item à afficher. getViewTypeCount() permet d'initialiser ce cache d'ailleurs.
    Ainsi on peut avoir plusieurs layout différents pour les items de la liste, tout en conservant les excellentes fonctionnalités de cache de la ListView.
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  5. #5
    Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2011
    Messages : 47
    Points : 46
    Points
    46
    Par défaut
    Citation Envoyé par nicroman Voir le message
    Je vais essayer de faire plus simple....

    Un "layout" est juste un fichier XML que le framework android est capable de transformer en objets (les views), correctement positionnés.


    Une "View" (ListView, Button, EditText, TextView, ImageView...) sont les éléments graphiques de bases (certains appellent celà des widgets, mais dans le monde Android on risque de les confondre avec les "app-widgets", d'ou le terme préféré de "view"). Aucune view ne peut avoir de "layout" puisque la view est justement le composant créé par la lecture d'un layout.
    Ok c'est plus clair
    Venant du monde web, ce concept me parait bizarre puisqu'avant je créais mon objet en HTML et je le mettait en forme avec le CSS, mais j'ai compris maintenant merci




    Citation Envoyé par nicroman Voir le message
    Ensuite, la ListView est un élément relativement simple (relativement parce qu'il y a un boulot de "cache" assez énorme): elle utilise un "ListAdapter" pour récupérer des items. Ces items sont just des données (j'y reviendrai plus loin).
    Pour chaque item à afficher, la ListView va demander à l'adapter la "View" qui correspond à l'item (fonction getView()).
    L'adapter est libre de renvoyer ce qu'il veut...

    Les adapters "simples" (et en particulier SimpleAdapter) renvoient toujours le même type de view... et cette view est crée à partir d'un layout passé en paramètre du constructeur (le parametre resource de SimpleAdapter). C'est donc le layout correspondant aux items.

    Toujours dans le cas de SimpleAdapter (qui est fort simpliste), chaque item est une HashMap. Et on passe même une correspondance entre les identifiants des views de ce layout des items, et les clés de cette map de valeurs.
    Il est bien évidant que c'est la porte ouverte aux erreurs (perte de typage des données, difficultés de trouver des erreurs en particulier de valeur "null", etc...).
    Ok, cette correspondance ID/Clef ça je m'en étais douté en écrivant mon message d'avant. Par contre pour cette porte ouverte aux bugs effectivement je n'avais pas fais attention à ça


    Citation Envoyé par nicroman Voir le message
    C'est pourquoi je recommande plutôt d'utiliser des ArrayAdapter<MonTypeDeDonnee> avec MonTypeDeDonnee
    Je vais jeter un coup d'oeil et faire des tests avec ça, sachant que je suis passé à l'IDE Android Studio je vais pouvoir me faire la main avec ça


    Citation Envoyé par nicroman Voir le message
    Et pour finir sur les "multiple" layout... Le getView() peut à priori renvoyer ce qu'il veut... Mais l'interêt est d'utiliser le "cache" de ListView (convertView de la fonction getView()) quand il est disponible. Pour cela, l'Adapter indique pour chaque item à la ListView de quel type il est ( fonction getItemViewType() ). Ce qui permet à la ListView de conserver un cache en fonction des types d'item à afficher. getViewTypeCount() permet d'initialiser ce cache d'ailleurs.
    Ainsi on peut avoir plusieurs layout différents pour les items de la liste, tout en conservant les excellentes fonctionnalités de cache de la ListView.
    Je vais prendre un peu de temps pour bien appréhender ce paragraphe
    En gros si j'ai bien compris c'est qu'il y a la possibilité d'avoir plusieurs styles différents selons les items dans la ListeView sans pour autant perdre en performance en bousillant le cache.

    Si c'est bien ça, je suppose qu'il faut quand même un minimum d'items pour que ça soit effectif ( si on a 4 items de 4 layouts différents, pas de cache donc ) mais ça tombe bien la ListView sera bien remplie


    Merci encore, je vais bosser tout ça ce dimanche

Discussions similaires

  1. Accéder aux propriétés du Layout depuis Adapter
    Par piero53 dans le forum Composants graphiques
    Réponses: 3
    Dernier message: 26/06/2013, 10h39
  2. [Mobile] adaptive layout
    Par vodasan dans le forum Webdesign & Ergonomie
    Réponses: 1
    Dernier message: 15/06/2012, 15h41
  3. Utilisation de layout dans un custom adapter
    Par Radagastlebrun dans le forum Composants graphiques
    Réponses: 0
    Dernier message: 09/11/2009, 15h03
  4. Langage le mieux adapté pour application client serveur ?
    Par guenus dans le forum Débats sur le développement - Le Best Of
    Réponses: 4
    Dernier message: 17/06/2002, 15h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo