ClassCastException cannot convert LinearLayout$LayoutParams to AbsListView$LayoutParams when setting ListView Header
android, android-listview, listview
Solution
My question is, why is this happening? First, on the conceptual side, why is it that when a header view is already in the layout the whole thing just dies? Is it because that view is effectively trying to be laid out twice: once for the header and once for the actual layout?
Your layout params are going crazy here, that's the problem.
- `inflate()` is called, assigning `ListView.LayoutParams` to `mLayout`, since you pass a ListView as the root. From the docs:
root: Optional view to be the parent of the generated hierarchy (if attachToRoot is true), or else simply an object that provides a set of LayoutParams values for root of the returned hierarchy (if attachToRoot is false.)
When you use `addView()`, it checks the type of the child's params. If it doesn't match, it converts it as best it can. It does this by copying the values over in a new constructor. So, your `mLayout` now has `LinearLayout.LayoutParams` attached.
Once you call `addHeaderView()`, `mLayout` is now a child of the listview. One of the things done during `ListView#setupChild()` is this:
`AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams();`
This is almost definitely where you're getting the ClassCastException. You just can't do a straight cast like that.
Secondly, why this exception? It seems awfully non-descriptive and it doesn't look like it captures the actual problem at all?
It's not that bad, but you have to understand how the layout system works. Could they do a simple check, and just throw an error or log message if it's not right? Sure. Could `ListView` try to gracefully handle the issue the way a `LinearLayout` does? Sure. But they don't.
It might be worth posting on the Android Developer's forum/group/tracker if you think it could be handled better.
Problem
First off, I've already figured out how to solve this bug, but at this point I'm just wondering why my fix works. The situation I was running into was that I was getting a `ClassCastException, cannot convert LinearLayout$LayoutParams to AbsListView$LayoutParams` when I tried to do the following (simplified for these purposes): ``` mLayout = (LinearLayout) getLayoutInflater() .inflate(R.layout.my_header_layout, getListView(), false); mRootView.addView(mLayout); getListView().addHeaderView(mLayout); getListView().setAdapter(mAdapter); ``` I eventually broke it down and discovered that the issue was fixed when I removed the call to `mRootView.addView(mLayout)` My two-fold question is, why is this happening? First, on the conceptual side, why is it that when a header view is already in the layout the whole thing just dies? Is it because that view is effectively trying to be laid out twice: once for the header and once for the actual layout? Secondly, why this exception? It seems awfully non-descriptive and it doesn't look like it captures the actual problem at all? Is this a case of a high level issue not being handled because a lower level function will just fail on the results anyway?