Android开发七:常用控件3--ListView(二)

 

接着上一节,上一节讲的是通过ArrayAdapter、SimpleAdapter给ListView绑定数据,它们的缺点就是在每一个item里面如果有按钮控件的话,点击是不管用的。这个时候我们就要用BaseAdapter。

这一节主要学习BaseAdapter,最后还会有使用继承ListActivity代替Activity的方法。

BaseAdapter是一个抽象类,要使用就必须要写一个类继承它,并实现它的方法。其中最重要的是getView方法。

这次我要实现的是在ListView中的每一行放上一个TextView和一个ImageButton,点击ImageButton会Toast出来点击的是哪一行。

主布局文件里面只有一个ListView控件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent"
 5     android:orientation="vertical" >
 6 
 7     <ListView
 8 android:id="@+id/listView1"
 9         android:layout_width="fill_parent"
10         android:layout_height="wrap_content" >
11     </ListView>
12 </LinearLayout>

每一列要显示的内容,新建一个xml文件,内容如下

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent"
 5     android:orientation="horizontal"
 6     android:descendantFocusability="blocksDescendants" >
 7 
 8     <TextView
 9 android:id="@+id/tvText"
10         android:layout_width="wrap_content"
11         android:layout_height="fill_parent"
12         android:gravity="left|center_vertical"
13         android:textSize="30sp" />
14 
15 
16     <ImageButton
17 android:id="@+id/ibView"
18         android:layout_width="wrap_content"
19         android:layout_height="wrap_content"
20         android:layout_alignParentRight="true"
21         android:layout_alignParentTop="true"
22         android:focusable="false"
23         android:src="@android:drawable/ic_menu_view"
24         android:background="#e0000000" />
25 
26 </RelativeLayout>

这个布局文件里面要注意的是android:descendantFocusability="blocksDescendants"和android:focusable="false",设置这两项以后ListView的item才可以获得焦点,否则焦点会再ImageButton上面。

实现过程比较复杂,定义一个ViewHolder来存放控件

//定义一个类来存放控件,对应每一行的布局文件中的控件
    class ViewHolder{
        public TextView itemtext;
        public ImageButton itemview;
    }

然后声明一个类来继承BaseAdapter,代码里面按照我的理解做了说明

 1 //声明一个类来继承BaseAdapter
 2     class myAdapter extends BaseAdapter{
 3         //定义一个LayoutInflater来导入资源文件用
 4         LayoutInflater inflater;
 5         //用来接收要绑定的数据
 6         ArrayList<HashMap<String, Object>> arrayList;
 7         //要绑定的资源文件id
 8         int resID;
 9         public myAdapter(Context context,ArrayList<HashMap<String, Object>> arrayList2,int resId){
10             this.inflater=LayoutInflater.from(context);
11             this.arrayList=arrayList2;
12             this.resID=resId;
13         }
14         //绑定的数据的长度,也就是ListView项的个数
15         @Override
16         public int getCount() {
17             // TODO Auto-generated method stub
18             return this.arrayList.size();
19         }
20 
21         @Override
22         public Object getItem(int position) {
23             // TODO Auto-generated method stub
24             return null;
25         }
26 
27         @Override
28         public long getItemId(int position) {
29             // TODO Auto-generated method stub
30             return 0;
31         }
32         //重要的方法
33         @Override
34         public View getView(final int position, View convertView, ViewGroup parent) {
35             //创建一个ViewHolder来盛放控件
36             ViewHolder vHolder;
37             //通过判断convertView是否为空来取得ViewHolder对象
38         //这个convertView就是ListView的一行
39             if (convertView==null) {
40                 //如果为null则从布局文件中导入
41                 convertView=inflater.inflate(this.resID, null);
42                 vHolder=new ViewHolder();
43                 vHolder.itemtext=(TextView)convertView.findViewById(R.id.tvText);
44                 vHolder.itemview=(ImageButton)convertView.findViewById(R.id.ibView);
45                 //setTag方法用来设置与视图关联的标签,我的理解就是把和它相关的ViewHolder存储起来,到用的时候再拿出来
46                 convertView.setTag(vHolder);
47             } else {
48                 //如果不为null就直接通过getTag取出来
49                 vHolder=(ViewHolder)convertView.getTag();
50             }
51             //然后给ViewHolder对象的每一项赋值
52             vHolder.itemtext.setText(this.arrayList.get(position).get("text").toString());
53             //添加按钮的点击事件
54             vHolder.itemview.setOnClickListener(new OnClickListener(){
55 
56                 @Override
57                 public void onClick(View v) {
58                     Toast.makeText(ListView_BaseAdapter2.this, "ImageButton "+(position+1)+"clicked!", Toast.LENGTH_SHORT).show();
59                 }
60             });
61             return convertView;
62         }
63     }

这里定义一个方法来生成数据,我测试的是20000行

 1     //定义一个生成数据的方法,因为HashMap的键对应的值可能是String或者是资源的ID,所以这里用的是HashMap<String, Object>
 2     private ArrayList<HashMap<String, Object>> getData() {
 3         ArrayList<HashMap<String, Object>> aList=new ArrayList<HashMap<String, Object>>();
 4         for (int i = 0; i < 20000; i++) {
 5             HashMap<String, Object> map=new HashMap<String, Object>();
 6             map.put("text", "第"+(i+1)+"行");
 7             aList.add(map);
 8         }
 9         return aList;
10     }

最后在ListView上面绑定数据

1      //获取ListView对象
2         lView=(ListView)findViewById(R.id.listView1);
3         //使用创建的adatper对象绑定数据
4         myAdapter adapter=new myAdapter(ListView_BaseAdapter2.this, getData(), R.layout.item);
5         lView.setAdapter(adapter);

这样就实现了每一行的ImageButton可点击,弹出Toast消息,显示所在行。测试的效果还算可以,2000行数据在我的V880上面平均是2.5秒的时间,打开以后滑动十分流畅。
下面是本次的完整代码

View Code
  1 package com.yyj.ListView_BaseAdapter;
  2 
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 
  6 import android.app.Activity;
  7 import android.content.Context;
  8 import android.os.Bundle;
  9 import android.view.LayoutInflater;
 10 import android.view.View;
 11 import android.view.View.OnClickListener;
 12 import android.view.ViewGroup;
 13 import android.widget.BaseAdapter;
 14 import android.widget.ImageButton;
 15 import android.widget.ListView;
 16 import android.widget.TextView;
 17 import android.widget.Toast;
 18 
 19 public class ListView_BaseAdapter2 extends Activity {
 20     ListView lView;
 21     @Override
 22     protected void onCreate(Bundle savedInstanceState) {
 23         super.onCreate(savedInstanceState);
 24         setContentView(R.layout.main);
 25         //获取ListView对象
 26         lView=(ListView)findViewById(R.id.listView1);
 27         //使用创建的adatper对象绑定数据
 28         myAdapter adapter=new myAdapter(ListView_BaseAdapter2.this, getData(), R.layout.item);
 29         lView.setAdapter(adapter);
 30     }
 31     //定义一个生成数据的方法,因为HashMap的键对应的值可能是String或者是资源的ID,所以这里用的是HashMap<String, Object>
 32     private ArrayList<HashMap<String, Object>> getData() {
 33         ArrayList<HashMap<String, Object>> aList=new ArrayList<HashMap<String, Object>>();
 34         for (int i = 0; i < 20000; i++) {
 35             HashMap<String, Object> map=new HashMap<String, Object>();
 36             map.put("text", "第"+(i+1)+"行");
 37             aList.add(map);
 38         }
 39         return aList;
 40     }
 41     //定义一个类来存放控件,对应每一行的布局文件中的控件
 42     class ViewHolder{
 43         public TextView itemtext;
 44         public ImageButton itemview;
 45     }
 46     //声明一个类来继承BaseAdapter
 47     class myAdapter extends BaseAdapter{
 48         //定义一个LayoutInflater来导入资源文件用
 49         LayoutInflater inflater;
 50         //用来接收要绑定的数据
 51         ArrayList<HashMap<String, Object>> arrayList;
 52         //要绑定的资源文件id
 53         int resID;
 54         public myAdapter(Context context,ArrayList<HashMap<String, Object>> arrayList2,int resId){
 55             this.inflater=LayoutInflater.from(context);
 56             this.arrayList=arrayList2;
 57             this.resID=resId;
 58         }
 59         //绑定的数据的长度,也就是ListView项的个数
 60         @Override
 61         public int getCount() {
 62             // TODO Auto-generated method stub
 63             return this.arrayList.size();
 64         }
 65 
 66         @Override
 67         public Object getItem(int position) {
 68             // TODO Auto-generated method stub
 69             return null;
 70         }
 71 
 72         @Override
 73         public long getItemId(int position) {
 74             // TODO Auto-generated method stub
 75             return 0;
 76         }
 77         //重要的方法
 78         @Override
 79         public View getView(final int position, View convertView, ViewGroup parent) {
 80             //创建一个ViewHolder来盛放控件
 81             ViewHolder vHolder;
 82             //通过判断convertView是否为空来取得ViewHolder对象
 83 //这个convertView就是ListView的一行
 84             if (convertView==null) {
 85                 //如果为null则从布局文件中导入
 86                 convertView=inflater.inflate(this.resID, null);
 87                 vHolder=new ViewHolder();
 88                 vHolder.itemtext=(TextView)convertView.findViewById(R.id.tvText);
 89                 vHolder.itemview=(ImageButton)convertView.findViewById(R.id.ibView);
 90                 //setTag方法用来设置与视图关联的标签,我的理解就是把和它相关的ViewHolder存储起来,到用的时候再拿出来
 91                 convertView.setTag(vHolder);
 92             } else {
 93                 //如果不为null就直接通过getTag取出来
 94                 vHolder=(ViewHolder)convertView.getTag();
 95             }
 96             //然后给ViewHolder对象的每一项赋值
 97             vHolder.itemtext.setText(this.arrayList.get(position).get("text").toString());
 98             //添加按钮的点击事件
 99             vHolder.itemview.setOnClickListener(new OnClickListener(){
100 
101                 @Override
102                 public void onClick(View v) {
103                     Toast.makeText(ListView_BaseAdapter2.this, "ImageButton "+(position+1)+"clicked!", Toast.LENGTH_SHORT).show();
104                 }
105             });
106             return convertView;
107         }
108     }
109 }

效果图:

最后附上源文件:ListView_BaseAdapter.zip

下面在简单的说一下,在主布局文件中只有一个ListView的时候,我们可以使用ListActivity,ListActivity继承自Activity类,默认绑定了一个ListView,并提供一些处理ListView的操作。

直接贴上代码,里面要注意的地方已经注释上了

main.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent"
 5     android:orientation="vertical" >
 6 
 7     <!-- 注意这个ListView的id写法,这个是默认的id -->
 8     <ListView 
 9 android:id="@+id/android:list"
10         android:layout_width="fill_parent"
11         android:layout_height="wrap_content"
12 ></ListView>
13 </LinearLayout>

user.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="50dp"
 5     android:orientation="horizontal" >
 6     
 7     <TextView 
 8 android:id="@+id/uname"
 9         android:layout_width="fill_parent"
10         android:layout_height="fill_parent"
11         android:gravity="center"
12         android:layout_weight="1"/>
13     <TextView 
14 android:id="@+id/uage"
15         android:layout_width="fill_parent"
16         android:layout_height="fill_parent"
17         android:gravity="center"
18         android:layout_weight="1"/>
19 </LinearLayout>

ListViewTestActivity.java

 1 package com.yyj.ListViewTest;
 2 
 3 import java.util.ArrayList;
 4 import java.util.HashMap;
 5 
 6 import android.app.ListActivity;
 7 import android.os.Bundle;
 8 import android.view.View;
 9 import android.widget.ListView;
10 import android.widget.SimpleAdapter;
11 import android.widget.TextView;
12 import android.widget.Toast;
13 
14 //注意,这里继承的是ListActivity,不是Activity
15 public class ListViewTestActivity extends ListActivity {
16     /** Called when the activity is first created. */
17     @Override
18     public void onCreate(Bundle savedInstanceState) {
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.main);
21         
22         ArrayList<HashMap<String, Object>> arrayList=new ArrayList<HashMap<String,Object>>();
23         HashMap<String, Object> user1=new HashMap<String, Object>();
24         user1.put("username", "小明");
25         user1.put("userage", 24);
26         HashMap<String, Object> user2=new HashMap<String, Object>();
27         user2.put("username", "小红");
28         user2.put("userage", 22);
29         HashMap<String, Object> user3=new HashMap<String, Object>();
30         user3.put("username", "小丽");
31         user3.put("userage", 24);
32         
33         for(int i=0;i++<5;){
34             arrayList.add(user1);
35             arrayList.add(user2);
36             arrayList.add(user3);
37         }
38         
39         SimpleAdapter adapter=new SimpleAdapter(ListViewTestActivity.this, arrayList, R.layout.user, new String[]{"username","userage"},new int[]{R.id.uname,R.id.uage} );
40         //ListActivity提供的绑定数据的方法
41         setListAdapter(adapter);
42     }
43 
44     //ListView每一项点击事件,覆盖父类的方法和以前用过的匿名内部类方法不同
45     @Override
46     protected void onListItemClick(ListView l, View v, int position, long id) {
47         String str=((TextView)v.findViewById(R.id.uname)).getText().toString()+"今年"+((TextView)v.findViewById(R.id.uage)).getText().toString();
48         Toast.makeText(ListViewTestActivity.this,str, Toast.LENGTH_LONG).show();
49         
50         super.onListItemClick(l, v, position, id);
51     }
52     
53 }

效果图:


 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值