Bonjour à tous,
Je rencontre quelques difficultés pour mettre en place une listeView dans laquelle les éléments sont rangés par ordre alphabétique. Ce que je veux faire, dans ce cas, c'est lire un fichier xml contenant des informations sur des musiques, puis les classé par ordre alphabétique en affichant le nom et le genre. Le tout séparé en section (comme pour les contacts).
Pour cela, j'ai donc deux layouts, et deux Adapter personnalisés. Un pour gérer les sections, un autre pour l'affichage de la liste avec les informations personnalisé. En faisant des tests, j'ai essayé d'afficher une liste simple avec des sections, cela fonctionne. J'ai également essayé d'afficher ma liste avec les infos que je veux, ça marche aussi. Par contre, lorsque je combine, les deux, j'ai une erreur d'exécution lorsque j'essaye de scroller dans la liste. Pourtant, elle s'affiche correctement au lancement de l'application (et avec l'aspect voulu).
Voici le code que j'utilise. D'abord l'Adapter qui permet de gérer les sections :
L'Adapter pour l'affichage d'une listView personnalisée :
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 abstract public class MusicAdapter extends BaseAdapter{ abstract protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent); private List<Section> sections = new ArrayList<Section>(); private static int TYPE_SECTION_HEADER = 0; public MusicAdapter() { super(); } public void addSection(String caption, ItemAdapter adapter){ sections.add(new Section(caption, adapter)); } public Object getItem(int position){ for (Section section : this.sections){ if (position == 0){ return section; } int size = section.adapter.getCount() + 1; if (position < size){ return section.adapter.getItem(position - 1); } position -= size; } return null; } public int getCount(){ int total = 0; for (Section section : this.sections){ total += section.adapter.getCount() + 1; } return total; } public int getItemViewType(int position){ int typeOffset = TYPE_SECTION_HEADER + 1; for (Section section : this.sections) { if (position == 0) { return (TYPE_SECTION_HEADER); } int size = section.adapter.getCount() + 1; if (position < size) { return (typeOffset + section.adapter .getItemViewType(position - 1)); } position -= size; typeOffset += section.adapter.getViewTypeCount(); } return -1; } public boolean areAllItemsSelectable(){ return false; } public boolean isEnabled(int position) { return (getItemViewType(position) != TYPE_SECTION_HEADER); } @Override public View getView(int position, View convertView, ViewGroup parent){ int sectionIndex = 0; for (Section section : this.sections){ if (position == 0){ return (getHeaderView(section.caption, sectionIndex, convertView, parent)); } int size = section.adapter.getCount() + 1; if (position < size){ return (section.adapter.getView(position - 1, convertView, parent)); } position -= size; sectionIndex++; } return null; } @Override public long getItemId(int position){ return position; } class Section { String caption; ItemAdapter adapter; Section(String caption, ItemAdapter adapter) { this.caption = caption; this.adapter = adapter; } } }
Et enfin, l'activité qui est censé faire l'affichage :
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
44
45
46
47
48
49
50
51
52
53
54 public class ItemAdapter extends BaseAdapter{ private ListeMusicContainer<Music> mList; private LayoutInflater mInflater; public ItemAdapter(Context context, ListeMusicContainer<Music> musics){ mInflater = LayoutInflater.from(context); mList = musics; } @Override public int getCount() { return mList.size(); } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null){ convertView = mInflater.inflate(R.layout.list_item, null); holder = new ViewHolder(); holder.nom = (TextView) convertView.findViewById(R.id.nomAlbum); holder.genre = (TextView) convertView.findViewById(R.id.genreAlbum); convertView.setTag(holder); } else{ holder = (ViewHolder) convertView.getTag(); } holder.nom.setText(mList.getItem(position).getNom()); holder.genre.setText(mList.getItem(position).getGenre()); return convertView; } static class ViewHolder{ TextView nom; TextView genre; } }
J'obtiens les log suivants avec logcat au moment du plantage :
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
44
45
46
47
48
49
50
51
52
53 public class TestView extends ListActivity { /** Called when the activity is first created. */ private ListView mListView; private static String[] items; private XmlDataParser mParser; private ListeMusicContainer<Music> mList; private MusicAdapter mAdapter = new MusicAdapter() { protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent) { TextView result = (TextView) convertView; if (convertView == null) { result = (TextView) getLayoutInflater().inflate( R.layout.header, null); } result.setText(caption); return (result); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mParser = new XmlDataParser(); mList = mParser.parseXml(this); ListeMusicContainer<Music> groupe = new ListeMusicContainer<Music>(); String currLetter = null; for (int i = 0; i < mList.size(); i++){ if (!mList.getItem(i).getLabel().equalsIgnoreCase(currLetter) && currLetter != null){ mAdapter.addSection(mList.getItem(i).getLabel().toUpperCase(), new ItemAdapter(this, groupe)); groupe = new ListeMusicContainer<Music>(); currLetter = mList.getItem(i).getLabel(); } if (currLetter == null){ currLetter = mList.getItem(i).getLabel(); } groupe.addData(mList.getItem(i)); } setListAdapter(mAdapter); } }
Les données sont récupérées d'un fichier xml, et le sont vraisemblablement correctement puisque j'arrive à les afficher sans erreurs en faisant une liste simple. J'ai également essayé en mettant des données en dur pour remplir la liste, ça fonctionne un peu plus longtemps avant de planter avec le même message d'erreur.
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 I/ActivityManager( 42): Displayed activity com.view/.TestView: 1480 ms (total 1480 ms) D/dalvikvm( 975): GC_EXTERNAL_ALLOC freed 1214 objects / 78504 bytes in 96ms D/AndroidRuntime( 975): Shutting down VM W/dalvikvm( 975): threadid=1: thread exiting with uncaught exception (group=0x4 001d800) E/AndroidRuntime( 975): FATAL EXCEPTION: main E/AndroidRuntime( 975): java.lang.NullPointerException E/AndroidRuntime( 975): at com.view.ItemAdapter.getView(ItemAdapter.java :51) E/AndroidRuntime( 975): at com.view.MusicAdapter.getView(Music Adapter.java:91) E/AndroidRuntime( 975): at android.widget.AbsListView.obtainView(AbsList View.java:1294) E/AndroidRuntime( 975): at android.widget.ListView.makeAndAddView(ListVi ew.java:1727) E/AndroidRuntime( 975): at android.widget.ListView.fillDown(ListView.jav a:652) E/AndroidRuntime( 975): at android.widget.ListView.fillGap(ListView.java :623) E/AndroidRuntime( 975): at android.widget.AbsListView.trackMotionScroll( AbsListView.java:2944) E/AndroidRuntime( 975): at android.widget.AbsListView.onTouchEvent(AbsLi stView.java:2065) E/AndroidRuntime( 975): at android.widget.ListView.onTouchEvent(ListView .java:3315) E/AndroidRuntime( 975): at android.view.View.dispatchTouchEvent(View.jav a:3766) E/AndroidRuntime( 975): at android.view.ViewGroup.dispatchTouchEvent(Vie wGroup.java:897) E/AndroidRuntime( 975): at android.view.ViewGroup.dispatchTouchEvent(Vie wGroup.java:936) E/AndroidRuntime( 975): at android.view.ViewGroup.dispatchTouchEvent(Vie wGroup.java:936) E/AndroidRuntime( 975): at android.view.ViewGroup.dispatchTouchEvent(Vie wGroup.java:936) E/AndroidRuntime( 975): at com.android.internal.policy.impl.PhoneWindow$ DecorView.superDispatchTouchEvent(PhoneWindow.java:1671) E/AndroidRuntime( 975): at com.android.internal.policy.impl.PhoneWindow. superDispatchTouchEvent(PhoneWindow.java:1107) E/AndroidRuntime( 975): at android.app.Activity.dispatchTouchEvent(Activ ity.java:2086) E/AndroidRuntime( 975): at com.android.internal.policy.impl.PhoneWindow$ DecorView.dispatchTouchEvent(PhoneWindow.java:1655) E/AndroidRuntime( 975): at android.view.ViewRoot.handleMessage(ViewRoot. java:1785) E/AndroidRuntime( 975): at android.os.Handler.dispatchMessage(Handler.ja va:99) E/AndroidRuntime( 975): at android.os.Looper.loop(Looper.java:123) E/AndroidRuntime( 975): at android.app.ActivityThread.main(ActivityThrea d.java:4627) E/AndroidRuntime( 975): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 975): at java.lang.reflect.Method.invoke(Method.java:5 21) E/AndroidRuntime( 975): at com.android.internal.os.ZygoteInit$MethodAndA rgsCaller.run(ZygoteInit.java:868) E/AndroidRuntime( 975): at com.android.internal.os.ZygoteInit.main(Zygot eInit.java:626) E/AndroidRuntime( 975): at dalvik.system.NativeStart.main(Native Method) W/ActivityManager( 42): Force finishing activity com.view/.TestView
Je sais vraiment pas d'où peut venir le problème donc si l'un de vous à une idée, ce serait vraiment super.
Merci d'avance
Partager