1. 当自定义一个LinearLayout 的子类作为ListView的ItemView
当我们需要使用列表显示数据的时候,ListView和Adapter是必须用到的api,其中Adapter中的getView方法起着给ListView创建ItemView的作用,ItemView中如何布局,显示什么内容,都是由getView方法决定的。我们应该如何布局ItemView呢,一般的我们都会创建一个布局的子类,例如这样
private class HahaItem extends LinearLayout {
public int id;
public TextView mDate;
public TextView mContent;
public TextView mPublisher;
public ImageView mUserIcon;
public HahaItem(Context context) {
super (context);
setupUI();
}
private void setupUI() {
View.inflate(getContext(), R.layout.list_haha_item, this );
mDate = (TextView) this .findViewById(R.id.haha_pubdate);
mContent = (TextView) this .findViewById(R.id.haha_content);
mPublisher = (TextView) this .findViewById(R.id.haha_publisher);
/**
* 设置中文汉字的字体为bold,在TextView中设置textstyle=bold 仅对英文字符有效,必须使用
* 下述方法设置中文的字体为bold
* */
TextPaint tp = mPublisher.getPaint();
tp.setFakeBoldText( true );
mUserIcon = (ImageView) this .findViewById(R.id.haha_head_img);
}
}
R.layout.list_haha_item 布局方式如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_height="wrap_content" android:layout_width="fill_parent"> <TextView android:id="@+id/haha_content" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="17sp" android:textStyle="normal" android:typeface="monospace" android:paddingLeft="18dip" android:paddingRight="18dip" android:layout_marginTop="18dip" android:lineSpacingExtra="5dip" android:textScaleX="1.1" android:maxLines="5" android:layout_marginBottom="18dip" android:textColor="@color/dark_gray" /> <RelativeLayout android:id="@+id/haha_bottombar" android:layout_width="fill_parent" android:layout_height="46dip" android:background="@drawable/test" android:layout_marginTop="2dip"> <LinearLayout android:id="@+id/pub" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentLeft="true"> <ImageView android:id="@+id/haha_head_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:maxHeight="25dip" android:adjustViewBounds="true" android:maxWidth="25dip" android:baselineAlignBottom="true" android:layout_marginTop="7dip" android:layout_marginLeft="5dip" /> <TextView android:id="@+id/haha_publisher" android:layout_marginLeft="10dip" android:paddingLeft="5dip" android:layout_width="wrap_content" android:layout_height="fill_parent" android:singleLine="true" android:textStyle="bold" android:textColor="#889db6" android:gravity="center_vertical" /> </LinearLayout> <TextView android:id="@+id/haha_pubdate" android:layout_width="wrap_content" android:layout_height="fill_parent" android:singleLine="true" android:layout_alignParentRight="true" android:textStyle="normal" android:gravity="center_vertical" android:textColor="#7b7b7b" android:layout_alignParentBottom="true" android:textSize="14sp" /> </RelativeLayout> </LinearLayout>
这样的话,在getView中可以直接new出一个对象来使用,可使代码变的整洁。
但是这样会出现一个问题,就是HahaItem下又嵌套了一个LinearLayout,视图层上多了一层LinearLayout,而这一层是很没必要的,怎么去掉这一层呢?
目前有两种办法,一种是完全自定义HahaItem,将他做成一个类似于系统view,例如TextView等等的一个控件,这样做很好,但是很麻烦
还有一种就是使用merge标签,将xml布局中的顶层LinearLayout改成merge,同时将android:orientation="vertical" android:layout_height="wrap_content"android:layout_width="fill_parent 等属性都去掉,因为就算写上了也不起作用。
在HahaItem的setupUI方法中使用代码动态的设置它的各种属性。这样就会减少多余的LinearLayout层了。
2. 当使用代码创建一个控件时,如何设置它的layoutParams?
从下面的错误代码说起:
public View getView( int position, View convertView, ViewGroup parent) {
TextView item;
if (convertView == null ) {
item = new TextView(getContext());
item.setLayoutParams( new AbsListView.LayoutParams(AbsListView.LayoutParams.FILL_PARENT, 60 ));
} else {
item = (TextView) convertView;
}
final JiFengItemInfo info = mInfoList.get(position);
item.setText(info.name);
return item;
}
item.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, 60)); 这样是不对的,为什么?
先看一张图:
从这张图上可以看出view控件自身的layoutParams是由它的parent容器决定的,也就是说给一个view设置layout属性的时候,必须设置它的父容器的layoutParams,这也就是为什么上面的代码中必须要item.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.FILL_PARENT, 60));这样写才对的元婴,item的父容器是ListView,所以必须设置ListView的LayouParams。
3. ArrayAdapter的getView方法中发生的ClassCastException
@Override
public View getView( int position, View convertView, ViewGroup parent) {
TextView tv;
if (convertView == null ) {
tv = (TextView) View.inflate(getContext(), mResource, null );
} else {
tv = (TextView) convertView;
}
JiFengItemInfo info = getItem(position);
tv.setTag(getItem(position));
tv.setText(info.name);
return tv;
}
说明:
1. mResource代表的xml布局文件是个复杂布局,顶层是LinearLayout,包含一个TextView
2. getView方法是ArrayAdapter中的方法
为什么会出现类转换异常?
虽然getView方法返回的是TextView,但是convertView的类型是LinearLayout,当执行 tv = (TextView) convertView;的时候就会抛出类转换异常。
TextView tv是LinearLayout中的一个子控件,他是依赖于LinearLayout存在的,虽然可以获取这个TextView对象,但是不能将他单独取出来,存放到ListView中,上面的代码,实际上存放到ListView中的ItemView是LinearLayout类型的。
这个错误很容易犯,下次注意。