ClassCastException when calling ListView.addHeaderView()?
I have a fairly complex layout (containing RelativeLayouts, TextViews and ImageViews) that I want to place above a listview. This view should scroll with the listview.
I tried adding the layout as a header to the listview using this code:
View v = inflater.inflate(R.layout.list_view, container, false);
View header = inflater.inflate(R.layout.header_layout, container, false);
// populate views in the header
mList = (ListView)v.findViewById(R.id.list);
mList.addHeaderView(header);
mAdapter = new ReviewsAdapter(getActivity());
mList.setAdapter(mAdapter); <-- error occurs here
ReviewsAdapter
is a custom adapter I've written which extends BaseAdapter
.
Upon executing the code, I get this error:
11-25 17:19:14.802: E/AndroidRuntime(1215): java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
11-25 17:19:14.802: E/AndroidRuntime(1215): at android.widget.ListView.clearRecycledState(ListView.java:513)
11-25 17:19:14.802: E/AndroidRuntime(1215): at android.widget.ListView.resetList(ListView.java:499)
11-25 17:19:14.802: E/AndroidRuntime(1215): at android.widget.ListView.setAdapter(ListView.java:442)
11-25 17:19:14.802: E/AndroidRuntime(1215): at com.coppi.storefront.product.ProductReviewsFragment.onCreateView(ProductReviewsFragment.java:104)
If I comment out the mList.addHeaderView(header)
line I do not get the error. I can also display the header layout without the listview with no problems.
I'm assuming this has something to do with the contents of the header layout but I'm not sure exactly what would be causing it.
Here is the header xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<RelativeLayout
android:id="@+id/header_section"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/margin_sides"
android:background="@color/pdp_availability_section_background" >
<TextView
android:id="@+id/header_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_sides"
android:paddingBottom="@dimen/margin_sides"
android:text="@string/ratings_reviews"
android:textColor="#000"
android:textSize="18dp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/body_section"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/header_section" >
<TextView
android:id="@+id/product_title"
style="@style/ProductTitleFont"
android:layout_marginBottom="@dimen/product_title_bottom_margin"
android:layout_marginLeft="@dimen/margin_sides"
android:layout_marginRight="@dimen/margin_sides" />
<RelativeLayout
android:id="@+id/attributes_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/product_title"
android:layout_centerHorizontal="true"
android:layout_margin="@dimen/margin_sides" >
<LinearLayout
android:id="@+id/overall_section"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="bottom" >
<TextView
android:id="@+id/overall_label"
style="@style/ProductTitleFont"
android:layout_width="wrap_content"
android:text="@string/overall_rating" />
<ImageView
android:id="@+id/overall_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:src="@drawable/icon_rating_empty" />
<ImageView
android:id="@+id/overall_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_rating_empty" />
<ImageView
android:id="@+id/overall_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_rating_empty" />
<ImageView
android:id="@+id/overall_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_rating_empty" />
<ImageView
android:id="@+id/overall_5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_rating_empty" />
<TextView
android:id="@+id/overall_score"
style="@style/ProductTitleFont"
android:layout_width="wrap_content"
android:layout_marginLeft="10dp"
android:text="4.6" />
</LinearLayout>
<Button
android:id="@+id/rate_review_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/overall_section"
android:layout_marginBottom="@dimen/margin_sides"
android:layout_marginTop="@dimen/margin_sides"
android:text="@string/rate_review_button_text" />
</RelativeLayout>
<View
android:id="@+id/attributes_divider"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_below="@id/attributes_section"
android:layout_marginBottom="@dimen/margin_sides"
android:layout_marginTop="@dimen/margin_sides"
android:background="@color/pdp_section_divider" />
<TextView
android:id="@+id/review_count"
style="@style/ProductTitleFont"
android:layout_width="wrap_content"
android:layout_below="@id/attributes_divider"
android:layout_marginLeft="@dimen/margin_sides"
android:text="0 " />
<TextView
style="@style/ProductTitleFont"
android:layout_width="wrap_content"
android:layout_alignBaseline="@id/review_count"
android:layout_marginRight="@dimen/margin_sides"
android:layout_toRightOf="@id/review_count"
android:text="@string/customer_reviews" />
<View
android:id="@+id/review_count_divider"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:layout_below="@id/review_count"
android:layout_marginBottom="@dimen/margin_sides"
android:layout_marginTop="@dimen/margin_sides"
android:background="@color/pdp_section_divider" />
</RelativeLayout>
</RelativeLayout>
Update: I tried reducing the header .xml file to just a single TextView and the problem continues. So I don't believe the problem is being cause by something in the xml.
FrameLayout
and AbsListView
convert their children layout params to FrameLayout.LayoutParams
and AbsListView.LayoutParams
. This is where the casting fails.
View header = View.inflate(this, R.layout.header_layout, null);
should fix it.
Edit: As mentioned in the comments, changing the ViewGroup Parameter of the inflate call also makes it work:
header = inflater.inflate(R.layout.header_layout, null, false);
Although Souvlaki's method will fix the issue and allow you to continue working. It is always best to give the view being inflated a reference to the container it will be in. This allows for Android to correctly inflate it for the right context.
What you should do is find the ListView
and then pass that to the inflate.
ListView listView = (ListView) layout.findViewById(R.id.listview);
View header = inflater.inflate(this, R.layout.header_layout, listView, false);
I see same situation. in my case, it's a trouble that call timing for ListView.addHeaderView().
Before: (Error)
ListView.addHeaderView() is called in Fragment.onCreateView() method.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_main, container, false);
mListView = (ListView) layout.findViewById(R.id.listview);
mListView.addHeaderView(inflater.inflate(R.layout.list_header_book, listview, false));
return layout;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new BookAdapter(getActivity(), mBookList);
mListView.setOnItemClickListener(mBookItemClickListener);
mListView.setAdapter(mAdapter);
}
After:(OK)
ListView.addHeaderView() is called in Fragment.onActivityCreated() method.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new BookAdapter(getActivity(), mBookList);
mListView = (ListView) getView().findViewById(R.id.listview);
mListView.setOnItemClickListener(mBookItemClickListener);
mListView.addHeaderView(LayoutInflater.from(getActivity()).inflate(R.layout.list_header_book, null));
mListView.setAdapter(mAdapter);
}