Pierre87 Posté(e) 21 mai 2010 Share Posté(e) 21 mai 2010 Comme je trouvais le BaseAdapter un peut trop simpliste, j'ai décidé d'en coder un assez sympa : SectionListAdapter :P (c'est assez proche de ExpandableMachin, mais sans le bling bling "expandable") Le principe : - ça s'utilise sur une ListView ou une ListActivity directement (pas besoin d'une nouvelle classe) - la liste est découpée en "section", et les section en "row" (lol iPhone) - SectionListAdapter hérite de BaseAdapter - Les méthodes de BaseAdapter sont déjà implémentées - Il y a de nouvelles méthodes à implémenter, avec "section+row" à la place de "position" Le point fort : on peut définir le nombre de sections, et la TAILLE d'une section. L'intérêt de pouvoir définir une taille pour une section, c'est qu'en définissant sa taille à 0, on peut la masquer \o/ Ok, on pouvait déjà faire ça avec le BaseAdapter, mais SectionListAdapter permet de le faire plus facilement, et plus proprement Il y a aussi un système de cache, mais il est à améliorer. Je me demande quelles sont les données intéressantes à mettre en cache ... public abstract class SectionListAdapter extends BaseAdapter { private HashMap sectionRows; public SectionListAdapter() { super(); this.sectionRows = new HashMap(); } public void notifyDataSetChanged() { this.sectionRows.clear(); super.notifyDataSetChanged(); // notify after clear } public int getCount() { int count = 0; int sectionCount = this.getSectionCount(); for (int section = 0; section < sectionCount; section++) { count += this.getRowCount(section); } return count; } public Object getItem(int position) { int[] sectionRow = this.getSectionRow(position); Object o = this.getItem(sectionRow[0], sectionRow[1]); return o; } public long getItemId(int position) { int[] sectionRow = this.getSectionRow(position); long id = this.getItemId(sectionRow[0], sectionRow[1]); return id; } public View getView(int position, View convertView, ViewGroup parent) { int[] sectionRow = this.getSectionRow(position); convertView = this.getView(sectionRow[0], sectionRow[1], convertView, parent); return convertView; } public int getItemViewType(int position) { int[] sectionRow = this.getSectionRow(position); int itemViewType = this.getItemViewType(sectionRow[0], sectionRow[1]); return itemViewType; } private int[] getSectionRow(int position) { int[] sectionRow = this.sectionRows.get(position); if (sectionRow == null) { int p = position; int sectionCount = this.getSectionCount(); for (int i = 0; i < sectionCount; i++) { int rowCount = this.getRowCount(i); if (p < rowCount) { sectionRow = new int[] { i, p }; break; } p -= rowCount; } if (sectionRow == null) { sectionRow = new int[] { -1, -1 }; } this.sectionRows.put(position, sectionRow); } return sectionRow; } public abstract int getSectionCount(); public abstract int getRowCount(int section); public abstract Object getItem(int section, int row); public abstract long getItemId(int section, int row); public abstract int getItemViewType(int section, int row); public abstract View getView(int section, int row, View convertView, ViewGroup parent); } Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Nivek Posté(e) 21 mai 2010 Share Posté(e) 21 mai 2010 Intéressant, une petite illustration de ce que cela permet de réaliser ? Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Pierre87 Posté(e) 22 mai 2010 Auteur Share Posté(e) 22 mai 2010 Imaginons une liste ayant cette structure : TITRE A a1 a2 a3 B b1 b2 C c1 c2 c3 c4 TITRE est une View unique, affiché en toute circonstance A B et C sont des sous titres, au début de groupes d'éléments (ce sont des vues du même type) a(n) b(n) et c(n) sont des éléments, ils utilisent tous le même type de vue Les données éléments des 3 groupes A B et C sont stockées dans 3 List indépendantes (pour une meilleure structuration) Si une List est vides, il n'y a aucun élément affiché, et le sous titre correspondant (A par exemple) n'est pas affiché De plus, si les 3 listes sont vides, je veux afficher une ligne "no result" (en plus du TITRE) Par conséquent : J'ai 8 "sections" : - TITRE - sous titre A - éléments a - sous titre B - éléments b - sous titre C - éléments c - no result J'ai 4 types de vue différentes : - TITRE - sous titre - éléments - no result (bon ok, c'est un peu compliqué, mais c'est un extrait simplifié d'un cas sur lequel je travaille) C'est tout à fait possible de le faire avec un simple ListAdapter Mais à mon avis, le code va être bien crade :D En utilisant SectionListAdapter, on peut structurer le code plus facilement \o/ Désolé de ne pas pouvoir fournir de code, mais je n'en ai pas sous la main, et je ne suis pas sûr que ce soit utile :/ Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Nivek Posté(e) 23 mai 2010 Share Posté(e) 23 mai 2010 Je pense que c'est déjà plus clair ! Merci ! ;-) Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Pierre87 Posté(e) 19 juin 2010 Auteur Share Posté(e) 19 juin 2010 en voilà une nouvelle version plus complète, plus optimisée :P public abstract class SectionListAdapter extends BaseAdapter { private SparseArray sectionRows; // cache section an row for a // position in the ListView private int[] rowCounts; // cache row count for a section public SectionListAdapter() { super(); this.sectionRows = new SparseArray(); this.updateRowCount(); } public void notifyDataSetChanged() { this.sectionRows.clear(); this.updateRowCount(); super.notifyDataSetChanged(); // notify after clear } public final int getCount() { int count = 0; int sectionCount = this.getSectionCount(); for (int section = 0; section < sectionCount; section++) { count += this.getRowCount(section); } return count; } public final Object getItem(int position) { int[] sectionRow = this.getSectionRow(position); Object o = this.getItem(sectionRow[0], sectionRow[1]); return o; } public final long getItemId(int position) { int[] sectionRow = this.getSectionRow(position); long id = this.getItemId(sectionRow[0], sectionRow[1]); return id; } public final View getView(int position, View convertView, ViewGroup parent) { int[] sectionRow = this.getSectionRow(position); convertView = this.getView(sectionRow[0], sectionRow[1], convertView, parent); return convertView; } public final int getItemViewType(int position) { int[] sectionRow = this.getSectionRow(position); int itemViewType = this.getItemViewType(sectionRow[0], sectionRow[1]); return itemViewType; } public final View getDropDownView(int position, View convertView, ViewGroup parent) { int[] sectionRow = this.getSectionRow(position); convertView = this.getDropDownView(sectionRow[0], sectionRow[1], convertView, parent); return convertView; } // Return the section and the row for a position (and save in cache) private int[] getSectionRow(int position) { int[] sectionRow = this.sectionRows.get(position); if (sectionRow == null) { int p = position; int sectionCount = this.getSectionCount(); for (int i = 0; i < sectionCount; i++) { int rowCount = this.rowCounts[i]; if (p < rowCount) { sectionRow = new int[] { i, p }; break; } p -= rowCount; } if (sectionRow == null) { sectionRow = new int[] { -1, -1 }; } this.sectionRows.put(position, sectionRow); } return sectionRow; } // Update the row counts cache private void updateRowCount() { int sectionCount = this.getSectionCount(); if (this.rowCounts == null || this.rowCounts.length != sectionCount) { this.rowCounts = new int[sectionCount]; } for (int i = 0; i < sectionCount; i++) { this.rowCounts[i] = this.getRowCount(i); } } // Return number of section // Don't forget to override getViewTypeCount() // SHOULD ALWAYS RETURN THE SAME NUMBER !!! public abstract int getSectionCount(); // Return number of row for a section public abstract int getRowCount(int section); // Return an item for a section and a row public abstract Object getItem(int section, int row); // Return an item id for a section and a row public abstract long getItemId(int section, int row); // Return a view type for a section and a row public abstract int getItemViewType(int section, int row); // Return a view for a section and a row public abstract View getView(int section, int row, View convertView, ViewGroup parent); // ??? public View getDropDownView(int section, int row, View convertView, ViewGroup parent) { return convertView; } } pour l'avoir utilisé, je la trouve super pratique pour réaliser des ListView assez complexes Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
steph68 Posté(e) 14 septembre 2012 Share Posté(e) 14 septembre 2012 Une copie d'écran peut être? Ca aiderait vraiment pas mal à visualiser le résultat final...... :) Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
steph68 Posté(e) 17 septembre 2012 Share Posté(e) 17 septembre 2012 Hello! :) Tout ça m'a l'air pas mal du tout, et pourrait me servir aussi. :P Mais juste pour améliorer ma compréhension, tu pourrais donner un exemple d'utilisation de ta classe dans un code STP? :) Merci. Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Recommended Posts
Rejoignez la conversation
Vous pouvez poster maintenant et vous enregistrez plus tard. Si vous avez un compte, connectez-vous maintenant pour poster.