现在的位置: 首页 > 综合 > 正文

ListView addHeaderView 报错的解决办法

2017年09月21日 ⁄ 综合 ⁄ 共 3446字 ⁄ 字号 评论关闭

在添加listview的 addheader方法时报错如下:

android.widget.RelativeLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParam

在main.xml文件中、

 <FrameLayout android:layout_width="fill_parent" android:layout_height="wrap_content"
                 android:id="@+id/online_album_detail_frame"
            android:layout_alignParentTop="true"
            >
    </FrameLayout>

<ListView> ***** </Listview>

我是将ListView上面的FrameLayout直接设置为listview的header。结果报错,原因:

在ListView源码里可以看到:

1 void resetList() { 
2 // The parent's resetList() will remove all views from the layout so we need to 
3 // cleanup the state of our footers and headers 
4clearRecycledState(mHeaderViewInfos); 
5 clearRecycledState(mFooterViewInfos); 
7 super.resetList(); 
9 mLayoutMode = LAYOUT_NORMAL; 
10 
12 private void clearRecycledState(ArrayList<FixedViewInfo> infos) { 
13 if (infos != null) {
14 final int count = infos.size(); 15 
 for (int i = 0; i < count; i++) { 
17 final View child = infos.get(i).view; 
18 final LayoutParams p = (LayoutParams) child.getLayoutParams();
19 if (p != null) { 
20 p.recycledHeaderFooter = false;  
 }  
 }

错误就是在第18行抛出的,这里的 mFooterViewInfos 实际上就是我们添加的Footer view的一个列表。代码里循环处理每个footer view,而在getLayoutParams()时,ListView要求必须是AbsListView的LayoutParams

修改Framelayout的LayoutParams为 AbsListView.LayoutParams同样报错,这是为什么呢?

因为在main.xml文件中一样用到了FrameLayout ,将其Params设置为AbsListview的Params 那么,外层嵌套的parent不能识别。

同样报cast 类型错误。

解决办法:

将FrameLayout 提取出来,放到一个单独的xml文件中

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <ImageView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/online_album_detail_imageview"
            android:layout_alignParentLeft="true"/>
    <TextView android:layout_width="fill_parent" android:layout_height="wrap_content"
              android:id="@+id/online_album_detail_tv"
              android:maxLines="2"
              android:textSize="@dimen/text_size_medium"
              android:layout_below="@+id/online_album_detail_imageview"
              android:layout_centerVertical="true"
              android:background="@color/online_list_bg"
              android:layout_marginLeft="10dp"
              android:ellipsize="end"
              android:layout_gravity="bottom"
            />
</FrameLayout

在代码中

通常添加头部的方法是 

1 LayoutInflater
lif = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2 View
headerView = lif.inflate(R.layout.header, 
null);
3 mListView.addHeaderView(headerView);


但是lif.inflate(R.layout.header, null)丢失了XML布局中根View的LayoutParam,应该使用的是 

1 lif.inflate(R.layout.header,
mListView, 
false);

LayoutInflater的作用很简单,就是将XML的布局文件“翻译”成相应的View对象,而且出于性能的考虑,LayoutInflater只能处理编译后的XML文件,而不能处理通常明文编码的XML文件。 
最常用的一个方法: 

1 View
inflate(
int resource,
ViewGroup root, 
boolean attachToRoot)


其中: 
resource是布局文件ID 
root是父ViewGroup对象, 
attachToRoot是是否将“翻译”出来的View添加到上面的root中 

root和attachToRoot是共同作用的: 
1,有root,同时attachToRoot为false,那么inflate()返回的就是“翻译”得到的view 
2,有root,同时attachToRoot为true,那么inflate()就是将“翻译”得到的view添加到root后,然后返回root 
3,无root,同时attachToRoot为false,那么inflate()返回的就是“翻译”得到的view。 
4,无root,同时attachToRoot为true,报错。 

另外,root还有一个重要的作用就是为“翻译”得到的view添加合适的LayoutParam,并且如果并不想将得到的View添加到root的话,传递何种root是并没有要求的,比如: 

1 View
view = mLayoutInflater.inflate(R.layout.header, 
new ListView(mContext), false);
2 View
view = mLayoutInflater.inflate(R.layout.header, 
new LinearLayout(mContext), false);
3 View
view = mLayoutInflater.inflate(R.layout.header, 
new RelativeLayout(mContext), false);

上面得到的View,除了view的LayoutParam分别为AbsListView.LayoutParams,LinearLayout.LayoutParams,RelativeLayout.LayoutParams之外,内容都一致。

抱歉!评论已关闭.