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类型的。

这个错误很容易犯,下次注意。

posted on 2011-03-08 22:50  Android火鸟  阅读(2964)  评论(0编辑  收藏  举报