Android: ClassCastException lors de l’ajout d’une vue d’en-tête à ExpandableListView

J’essaie d’append un en-tête à un ExpandableListView comme ceci:

headerView = View.inflate(this, R.layout.header, null); expandableListView.addHeaderView(headerView); expandableListView.setAdapter(new SectionedAdapter(this)); 

Ce qui me donne l’erreur suivante:

  12-08 16:23:42.354: ERROR/AndroidRuntime(421): Caused by:java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams 12-08 16:23:42.354: ERROR/AndroidRuntime(421): at android.widget.ListView.clearRecycledState(ListView.java:504) 12-08 16:23:42.354: ERROR/AndroidRuntime(421): at android.widget.ListView.resetList(ListView.java:490) 12-08 16:23:42.354:ERROR/AndroidRuntime(421):at android.widget.ListView.setAdapter(ListView.java:422) 12-08 16:23:42.354:ERROR/AndroidRuntime(421): at android.widget.ExpandableListView.setAdapter(ExpandableListView.java:475) 

Cela se produit lors de l’appel à expandableListView.setAdapter(new SectionedAdapter(this)) , mais je n’arrive pas à comprendre pourquoi. Des idées?

Ok, je l’ai compris. Je me suis débarrassé de l’erreur d’exécution en définissant par programme le LayoutParams de View sur ListView LayoutParams, comme ceci:

 headerView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.FILL_PARENT, ListView.LayoutParams.WRAP_CONTENT)); 

avant d’append la vue. La raison en est trouvée dans les documents Android:

http://developer.android.com/reference/android/view/View.html#setLayoutParams(android.view.ViewGroup.LayoutParams)

qui stipule que:

Ceux-ci fournissent des parameters au parent de cette vue en spécifiant comment il doit être organisé. Il existe de nombreuses sous-classes de ViewGroup.LayoutParams, qui correspondent aux différentes sous-classes de ViewGroup responsables de l’organisation de leurs enfants.

Donc, fondamentalement, si vous ajoutez une vue à une autre, vous DEVEZ définir les LayoutParams de la vue sur le type LayoutParams que le parent utilise ou vous obtiendrez une erreur d’exécution.

Même si la réponse ci-dessus peut fonctionner pour beaucoup, il y a toujours une meilleure explication. ClassCastException est le comportement normal après avoir appelé listview.addHeaderView ou listview.addFooterView .

La raison en est que l’adaptateur initial est enveloppé dans HeaderViewListAdapter . Pour obtenir votre adaptateur, utilisez ce code.

 YourAdapter ya = (YourAdapter) ((HeaderViewListAdapter)lv.getAdapter()).getWrappedAdapter(); 

Code pris ici

Dans mon cas, cela n’a pas fonctionné. J’ai dû définir un footerView sur mon listView avant de configurer son adaptateur. D’abord, j’ai initialisé my loadingView à partir d’un fichier de disposition dans la méthode OnCreate:

 LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); loadingView = layoutInflater.inflate(R.layout.loading_view, null); 

Ensuite, j’ai utilisé cette solution de contournement dans la même méthode:

 this.setIsLoading(true); listView.setAdapter(adapter); this.setIsLoading(false); 

 private void setIsLoading(boolean isLoading) { this.isLoading = isLoading; if (isLoading) { listView.addFooterView(loadingView); } else { listView.removeFooterView(loadingView); } } 

Vous devez mettre la vue parent à votre vue gonflée.

 ListView listview = (ListView) findViewById(R.id.listview); headerView = View.inflate(this, R.layout.header, listview, false); // set listview as parent view listview.addHeaderView(headerview);