(Android学习笔记三)自定义ListView


  ListView是Android开发中很常用的组件,上篇写到的TabHost的第三个Tab就是一个ListView,里面填充的是从数据库中得到的一长串时间、体重数据,每一行一条数据。

  一般来说,列表的显示需要三个元素:
     1.视图  用来展示列表的View。
     2.适配器 用来把数据映射到ListView上的中介。分为三种:ArrayAdapter,SimpleAdapter和     SimpleCursorAdapter。
     3.数据 具体的将被映射的字符串,图片,或者基本组件。
   

   这里我的主Activity已经继承自TabActivity,而很多ListView例子都是继承自ListActivity。一女不能事二夫,java也不支持多继承(extends),必须自己来使用Widget组件ListView。实际上ListActivity和一般的Activity没什么区别,自己写写Adapter、listener实现ListActivity给我们简化的一些操作就行了。

(一) 在main.xml中要显示列表的地方加入ListView,这里的id可随便写,因为不继承ListActivity,不必写成android:id="@id/android:list"这种奇特的样子。.

    <LinearLayout
        android:id="@+id/linearLayout3"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
		<ListView 
		    android:id="@+id/list"
		    android:layout_width="fill_parent"
		    android:layout_height="fill_parent"
		/>
		    
    </LinearLayout>

(二) 新增一个vlist.xml,里面记录ListView的每一项的布局。这里的样式左边一张图片,中间是时间和体重数据,右边是删除按钮。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="horizontal" 
	android:layout_width="fill_parent"
	android:layout_height="fill_parent">


	<ImageView android:id="@+id/imgtest" 
		android:layout_width="wrap_content"
		android:layout_height="wrap_content" 
		android:layout_margin="5px"/>

	<LinearLayout android:orientation="vertical"
		android:layout_width="wrap_content" 
		android:layout_height="wrap_content">

		<TextView android:id="@+id/title" 
			android:layout_width="wrap_content"
			android:layout_height="wrap_content" 
			android:textColor="#FFFFFFFF"
			android:textSize="22px" />
		<TextView android:id="@+id/info" 
			android:layout_width="wrap_content"
			android:layout_height="wrap_content" 
			android:textColor="#FFFFFFFF"
			android:textSize="13px" />

	</LinearLayout>


	<Button android:id="@+id/view_btn"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Remove"
		android:focusable="false"
		android:layout_gravity="bottom|right" />
</LinearLayout>

  这里将button设置为没有焦点是因为不这么做的话,运行时你会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点。



(三)主Activity:

加成员变量:

	protected ListView lv;
	private List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

在onCreate中加入:

        lv=(ListView)findViewById(R.id.list);
	generateData();//从数据库中读数据并加入到list变量中	
	MyAdapter adapter=new MyAdapter(this,list);//自己写的Adapter,响应删除按钮的点击事件
        lv.setAdapter(adapter);
其中generateData方法如下:从数据库读出数据,填充到HashMap中,每个map包含四个key(id,title,info,img),然后将该map加入到 list中。
	private void generateData() {
		db = sqlHelper.getWritableDatabase();  
		Cursor cursor = db.rawQuery("select id,weight,datetime(timestamp,'localtime') from tb3",null);	
		int index=0;//just for adding different img
		for (cursor.moveToFirst();!(cursor.isAfterLast());cursor.moveToNext()) 
		{   
		  index++;
		  Map<String, Object> map = new HashMap<String, Object>();
		  String myID=cursor.getString(cursor.getColumnIndex("id"));
	          String myDate = cursor.getString(cursor.getColumnIndex("datetime(timestamp,'localtime')")); 	        
	          double myWeight=cursor.getDouble(cursor.getColumnIndex("weight"));
	          map.put("id", myID);
	          map.put("title", "Record at:"+myDate);
	          map.put("info", "Weight:"+myWeight);
	          switch(index%3){
	          	case 1:
	          		map.put("img", R.drawable.i1);break;
	          	case 2:
	          		map.put("img",R.drawable.i2);break;
	          	default:
	          		map.put("img",R.drawable.i3);break;
	          }
	          list.add(map);
	    }
		db.close();
		
	}


(四) 自定义Adapter类。这个类颇费一番心机,有关难点请看注释:
public class MyAdapter extends BaseAdapter {
	private LayoutInflater mInflater;
	private Context context;
	private List<Map<String, Object>> mData;
 
	
	public MyAdapter(Context context)
	{
		this.context=context;
		this.mInflater=LayoutInflater.from(context);
	}
	
	public MyAdapter(Context context,List<Map<String, Object>> list)
	{
		this.mInflater=LayoutInflater.from(context);
		this.mData=list;//传递要显示的列表进来
		this.context=context;
	}
	@Override
	public int getCount() {
		return mData.size();
	}

	@Override
	public Object getItem(int position) {
		return null;
	}

	@Override
	public long getItemId(int position) {
		return 0;
	}
	//View中的setTag(Object)表示给View添加一个格外的数据,以后可以用getTag()将这个数据取出来。
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {

		/*Adapter的作用就是ListView界面与数据之间的桥梁,当列表里的每一项显示到页面时,
		 *都会调用Adapter的getView方法返回一个View。如果每个view都用inflate的话,列表项数一多就会占用极大的系统资源。
		 * View中的setTag(Object)表示给View添加一个格外的数据(ViewHolder类),以后可以用getTag()将这个数据取出来。
		 * 这样做可以优化性能!*/
		ViewHolder holder = null;
		if (convertView == null) {		
			holder=new ViewHolder();  
			convertView = mInflater.inflate(R.layout.vlist, null);
			holder.img = (ImageView)convertView.findViewById(R.id.imgtest);
			holder.title = (TextView)convertView.findViewById(R.id.title);
			holder.info = (TextView)convertView.findViewById(R.id.info);
			holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn);
			convertView.setTag(holder);	
		}else {	
			holder = (ViewHolder)convertView.getTag();
		}
		holder.img.setBackgroundResource((Integer)mData.get(position).get("img"));
		holder.title.setText((String)mData.get(position).get("title"));
		holder.info.setText((String)mData.get(position).get("info"));
		/*为什么还要加个StringHolder呢?将数据依附到button中,向button的OnClicklistener传参!*/
		StringHolder strholder=new StringHolder();
		strholder.title=(String)mData.get(position).get("title");
		strholder.info=(String)mData.get(position).get("info");
		strholder.id=(String) mData.get(position).get("id");
		holder.viewBtn.setTag(strholder);//setTag
		holder.viewBtn.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				/*尽管在代码中相隔这么近,但是这里是button的匿名响应函数的世界,
				 * 咫尺天涯,title、info这些参数可望而不可及。好在我们还有setTag和getTag!*/
				StringHolder holder=(StringHolder) v.getTag();
				final String strDataID=holder.id;//为什么是final,让后面的onclickListner认识啊!
				new AlertDialog.Builder(context)
				.setTitle("真的要删除"+holder.title+"吗?")
				.setMessage(holder.info)
				.setNegativeButton("取消", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						
					}
				})
				.setPositiveButton("确定", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						DBHelper sqlHelper;
						SQLiteDatabase db;
						sqlHelper = new DBHelper(context, "test.db", null, 2);  
					        db = sqlHelper.getWritableDatabase();  
					        //这里要获取id的值也是个问题,解决方法就是final
						db.delete("tb3", "id=?", new String[]{strDataID});
						db.close();
					}
				})
				.show();
			}
		});
		
		
		return convertView;
	}
	
 
	
	public final class ViewHolder{
		public ImageView img;
		public TextView title;
		public TextView info;
		public Button viewBtn;
	}
	
	public final class StringHolder{
		public String title;
		public String info;
		public String id;
	}
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值