Android控件开发——ListView

上篇博客解决了Android客户端通过WebService与服务器端程序进行交互的问题,这篇博客重点关注两个问题,一个是Android应用程序如何与本机文件型数据库SQLite进行交互,另一问题则是如何在ListView中按照我们想要的界面效果进行展示。限于篇幅这篇重点讲ListView,下篇博客重点阐述SQLite。

ListView是一个常用的数据显示控件,假设我们要做一个简单的界面,如图所示。

这张图是我直接从Android平板电脑(Android 4.2.2)上面截图下来的,就是一个普通的列表,能够点击报名按钮获取到对应行的信息。

这里面显示的数据是我从SQLite数据库中查询出来的,封装的类的代码如下:

[java]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  1. public class MyDatabaseHelper extends SQLiteOpenHelper {  
  2.   
  3.     private static final String name = "mydb.db";// SQLite数据库文件名  
  4.     private static final int version = 1;// SQLite数据库版本号  
  5.   
  6.     public MyDatabaseHelper(Context context) {  
  7.         super(context, name, null, version);  
  8.     }  
  9.   
  10.     @SuppressLint("SimpleDateFormat")  
  11.     @Override  
  12.     public void onCreate(SQLiteDatabase db) {  
  13.         try {  
  14.             // 开启事务  
  15.             db.beginTransaction();  
  16.             String sql = "create table jobInfo (name varchar(20),"  
  17.                     + "num integer," + "date varchar(10),"  
  18.                     + "description text)";  
  19.             db.execSQL(sql);  
  20.   
  21.             //测试插入10条数据  
  22.             for (int i = 0; i < 10; i++) {  
  23.                 db.execSQL(  
  24.                         "insert into jobInfo(name,num,date,description)values(?,?,?,?)",  
  25.                         new Object[] {  
  26.                                 "name" + i,  
  27.                                 i,  
  28.                                 new SimpleDateFormat("yyyy-MM-dd")  
  29.                                         .format(new Date()), "description" + i });  
  30.             }  
  31.   
  32.             // 标识事务成功  
  33.             db.setTransactionSuccessful();  
  34.         } finally {  
  35.             // 结束事务  
  36.             db.endTransaction();  
  37.         }  
  38.     }  
  39.   
  40.     @Override  
  41.     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  42.         //数据库升级操作  
  43.     }  
  44. }  

在需要创建数据库、插入数据的地方都可以实例化MyDatabaseHelper这个类,关于更多的SQLite的细节下篇博客将会进行详细的说明。

 

activity_main.xml布局文件:

 

[html]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:paddingBottom="@dimen/activity_vertical_margin"  
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  7.     android:paddingRight="@dimen/activity_horizontal_margin"  
  8.     android:paddingTop="@dimen/activity_vertical_margin" >  
  9.   
  10.     <LinearLayout  
  11.         android:id="@+id/head"  
  12.         android:layout_width="match_parent"  
  13.         android:layout_height="wrap_content"  
  14.         android:orientation="horizontal" >  
  15.   
  16.         <TextView  
  17.             android:layout_width="wrap_content"  
  18.             android:layout_height="wrap_content"  
  19.             android:text="岗位名称"  
  20.             android:textSize="24sp"  
  21.             android:width="150dip" />  
  22.   
  23.         <TextView  
  24.             android:layout_width="wrap_content"  
  25.             android:layout_height="wrap_content"  
  26.             android:text="岗位数量"  
  27.             android:textSize="24sp"  
  28.             android:width="150dip" />  
  29.   
  30.         <TextView  
  31.             android:layout_width="wrap_content"  
  32.             android:layout_height="wrap_content"  
  33.             android:text="发布日期"  
  34.             android:textSize="24sp"  
  35.             android:width="150dip" />  
  36.   
  37.         <TextView  
  38.             android:layout_width="wrap_content"  
  39.             android:layout_height="wrap_content"  
  40.             android:text="岗位描述"  
  41.             android:textSize="24sp"  
  42.             android:width="550dip" />  
  43.     </LinearLayout>  
  44.   
  45.     <ListView  
  46.         android:id="@id/android:list"  
  47.         android:layout_width="wrap_content"  
  48.         android:layout_height="wrap_content"  
  49.         android:layout_below="@+id/head" >  
  50.     </ListView>  
  51.   
  52. </RelativeLayout>  

可以看到这是一个相对布局,里面有一个线性布局,线性布局里面又放置了4个TextView作为ListView数据的标题。下面直接是一个ListView控件,由于这是相对布局,为了让ListView显示在“表头”下面,我们设置了layout_below属性。此外要注意ListView的id的写法。

 

接着按照界面的要求,我们准备一下ListView加载布局文件的内容,我们起名为:list_item.xml。

list_item.xml:

 

[html]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  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="match_parent"  
  5.     android:orientation="horizontal" >  
  6.   
  7.     <TextView  
  8.         android:id="@+id/name"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:textSize="24sp"  
  12.         android:width="150dip" />  
  13.   
  14.     <TextView  
  15.         android:id="@+id/num"  
  16.         android:layout_width="wrap_content"  
  17.         android:layout_height="wrap_content"  
  18.         android:textSize="24sp"  
  19.         android:width="150dip" />  
  20.   
  21.     <TextView  
  22.         android:id="@+id/date"  
  23.         android:layout_width="wrap_content"  
  24.         android:layout_height="wrap_content"  
  25.         android:textSize="24sp"  
  26.         android:width="150dip" />  
  27.   
  28.     <TextView  
  29.         android:id="@+id/description"  
  30.         android:layout_width="wrap_content"  
  31.         android:layout_height="wrap_content"  
  32.         android:textSize="24sp"  
  33.         android:width="550dip" />  
  34.   
  35.     <Button  
  36.         android:id="@+id/btn"  
  37.         android:layout_width="wrap_content"  
  38.         android:layout_height="wrap_content"  
  39.         android:focusable="false"  
  40.         android:focusableInTouchMode="false"  
  41.         android:text="报名"  
  42.         android:width="150dip"  
  43.         android:textSize="24sp" />  
  44.   
  45. </LinearLayout>  

这也是一个普通的线性布局,设置orientation为horizontal(水平)。

 

布局文件准备好,下面我们准备写代码了。

我们让MainActivity这个类继承自ListActivity,完整的代码如下:

 

[csharp]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  1. public class MainActivity extends ListActivity {  
  2.   
  3.     List<Map<String, Object>> list;  
  4.   
  5.     @Override  
  6.     protected void onCreate(Bundle savedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.         setContentView(R.layout.activity_main);  
  9.   
  10.         list = new ArrayList<Map<String, Object>>();  
  11.         //初始化SQLite数据库操作类对象  
  12.         MyDatabaseHelper dbHelper = new MyDatabaseHelper(MainActivity.this);  
  13.           
  14.         //查询数据库返回Cursor(游标)对象  
  15.         Cursor cursor = dbHelper.getReadableDatabase().query("jobInfo",  
  16.                 new String[] { "name", "num", "date", "description" }, null,  
  17.                 null, null, null, "name");  
  18.           
  19.         //将结果集封装到List<Map<String,Object>>数据结构当中  
  20.         while (cursor.moveToNext()) {  
  21.             Map<String, Object> map = new HashMap<String, Object>();  
  22.             map.put("name", cursor.getString(0));  
  23.             map.put("num", cursor.getInt(1));  
  24.             map.put("date", cursor.getString(2));  
  25.             map.put("description", cursor.getString(3));  
  26.             map.put("btn", R.drawable.ic_launcher);  
  27.             list.add(map);  
  28.         }  
  29.         //查询完毕,记得及时关闭数据库链接  
  30.         cursor.close();  
  31.         MyButtonAdapter adapter = new MyButtonAdapter(MainActivity.this, list,  
  32.                 R.layout.list_item, new String[] { "name", "num", "date",  
  33.                         "description", "btn" }, new int[] { R.id.name,  
  34.                         R.id.num, R.id.date, R.id.description, R.id.btn });  
  35.   
  36.         //给ListView设置数据填充适配器  
  37.         ListView listView = (ListView) findViewById(android.R.id.list);  
  38.         listView.setAdapter(adapter);  
  39.     }  
  40.   
  41.     @Override  
  42.     protected void onListItemClick(ListView l, View v, int position, long id) {  
  43.         //ListView的  
  44.         @SuppressWarnings("unchecked")  
  45.         Map<String, Object> map = (HashMap<String, Object>) l  
  46.                 .getItemAtPosition(position);  
  47.         Toast.makeText(MainActivity.this,  
  48.                 "您点击了:" + map.get("name").toString() + "岗位!",  
  49.                 Toast.LENGTH_SHORT).show();  
  50.     }  
  51.       
  52.     public class MyButtonAdapter extends BaseAdapter {  
  53.   
  54.         private class ButtonViewHolder {  
  55.             TextView name;  
  56.             TextView num;  
  57.             TextView date;  
  58.             TextView description;  
  59.             Button btn;  
  60.         }  
  61.   
  62.         private Context mContext;  
  63.         private List<Map<String, Object>> mList;  
  64.         private ButtonViewHolder holder;  
  65.         private LayoutInflater mInflater;  
  66.         private String[] keyString;  
  67.         private int[] valueViewID;  
  68.   
  69.         // 构造函数初始化变量  
  70.         public MyButtonAdapter(Context context, List<Map<String, Object>> list,  
  71.                 int resource, String[] from, int[] to) {  
  72.             this.mContext = context;  
  73.             this.mList = list;  
  74.   
  75.             // 获得布局文件对象  
  76.             mInflater = (LayoutInflater) context  
  77.                     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  78.             keyString = new String[from.length];  
  79.             valueViewID = new int[to.length];  
  80.   
  81.             // 复制数组  
  82.             System.arraycopy(from, 0, keyString, 0, from.length);  
  83.             System.arraycopy(to, 0, valueViewID, 0, to.length);  
  84.         }  
  85.   
  86.         @Override  
  87.         public int getCount() {  
  88.             return list.size();  
  89.         }  
  90.   
  91.         @Override  
  92.         public Object getItem(int position) {  
  93.             return list.get(position);  
  94.         }  
  95.   
  96.         /** 
  97.          * 从list中移除某一项 
  98.          *  
  99.          * @param position 
  100.          */  
  101.         public void removeItem(int position) {  
  102.             list.remove(position);  
  103.             // 通知数据集已改变,请求自刷新  
  104.             this.notifyDataSetChanged();  
  105.         }  
  106.   
  107.         @Override  
  108.         public long getItemId(int position) {  
  109.             return position;  
  110.         }  
  111.   
  112.         @Override  
  113.         public View getView(int position, View convertView, ViewGroup parent) {  
  114.             if (convertView != null) {  
  115.                 holder = (ButtonViewHolder) convertView.getTag();  
  116.             } else {  
  117.                 convertView = mInflater.inflate(R.layout.list_item, null);  
  118.                 holder = new ButtonViewHolder();  
  119.                 holder.name = (TextView) convertView  
  120.                         .findViewById(valueViewID[0]);// 岗位名称  
  121.                 holder.num = (TextView) convertView  
  122.                         .findViewById(valueViewID[1]);// 岗位数量  
  123.                 holder.date = (TextView) convertView  
  124.                         .findViewById(valueViewID[2]);// 发布日期  
  125.                 holder.description = (TextView) convertView  
  126.                         .findViewById(valueViewID[3]);// 岗位描述  
  127.                 holder.btn = (Button) convertView.findViewById(valueViewID[4]);// 报名按钮  
  128.                 convertView.setTag(holder);  
  129.             }  
  130.             Map<String, Object> appInfo = mList.get(position);  
  131.             if (appInfo != null) {  
  132.                 String aname = (String) appInfo.get(keyString[0]);  
  133.                 Integer anum = (Integer) appInfo.get(keyString[1]);  
  134.                 String adate = (String) appInfo.get(keyString[2]);  
  135.                 String adescription = (String) appInfo.get(keyString[3]);  
  136.                 holder.name.setText(aname);  
  137.                 holder.num.setText(anum + "");  
  138.                 holder.date.setText(adate);  
  139.                 holder.description.setText(adescription);  
  140.   
  141.                 // 报名按钮事件  
  142.                 holder.btn.setOnClickListener(new lvButtonListener(position));  
  143.             }  
  144.             return convertView;  
  145.         }  
  146.   
  147.         class lvButtonListener implements OnClickListener {  
  148.             private int position;  
  149.   
  150.             lvButtonListener(int pos) {  
  151.                 position = pos;  
  152.             }  
  153.   
  154.             @Override  
  155.             public void onClick(View v) {  
  156.                 int vid = v.getId();  
  157.                 if (vid == holder.btn.getId()) {  
  158.                     String result = "" + "岗位名称:"  
  159.                             + list.get(position).get("name") + "\r\n" + "岗位人数:"  
  160.                             + list.get(position).get("num") + "\r\n" + "发布日期:"  
  161.                             + list.get(position).get("date") + "\r\n" + "岗位描述:"  
  162.                             + list.get(position).get("description") + "\r\n";  
  163.   
  164.                     new AlertDialog.Builder(MainActivity.this)  
  165.                             .setTitle("提示")  
  166.                             .setIcon(R.drawable.ic_launcher)  
  167.                             .setMessage(result + "\r\n" + "您确定要申请该岗位吗?")  
  168.                             .setPositiveButton(R.string.positive,  
  169.                                     new DialogInterface.OnClickListener() {  
  170.                                         @Override  
  171.                                         public void onClick(  
  172.                                                 DialogInterface dialog,  
  173.                                                 int which) {  
  174.                                             Toast toast = Toast  
  175.                                                     .makeText(  
  176.                                                             MainActivity.this,  
  177.                                                             "您点击了"  
  178.                                                                     + getResources()  
  179.                                                                             .getString(  
  180.                                                                                     R.string.positive)  
  181.                                                                     + "按钮,申请了"  
  182.                                                                     + list.get(  
  183.                                                                             position)  
  184.                                                                             .get("name")  
  185.                                                                     + "的岗位!",  
  186.                                                             Toast.LENGTH_SHORT);  
  187.                                             toast.setGravity(Gravity.CENTER, 0,  
  188.                                                     0);  
  189.                                             toast.show();  
  190.                                         }  
  191.                                     })  
  192.                             .setNegativeButton(R.string.negative,  
  193.                                     new DialogInterface.OnClickListener() {  
  194.                                         @Override  
  195.                                         public void onClick(  
  196.                                                 DialogInterface dialog,  
  197.                                                 int which) {  
  198.                                             Toast toast = Toast  
  199.                                                     .makeText(  
  200.                                                             MainActivity.this,  
  201.                                                             "您点击了"  
  202.                                                                     + getResources()  
  203.                                                                             .getString(  
  204.                                                                                     R.string.negative)  
  205.                                                                     + "按钮",  
  206.                                                             Toast.LENGTH_SHORT);  
  207.                                             toast.setGravity(Gravity.CENTER, 0,  
  208.                                                     0);  
  209.                                             toast.show();  
  210.                                         }  
  211.                                     }).create().show();  
  212.                     // 如果要删除行,可以调用此方法  
  213.                     // removeItem(position);  
  214.                 }  
  215.             }  
  216.         }  
  217.     }  
  218. }  


上面的代码有几个知识点需要注意:

 

1、SQLite数据库的查询操作

我们通过getReadableDatabase().query方法执行了查询操作,返回Cursor(游标,与JDBC中的ResultSet类似)对象。

2、ListView控件使用(重点)

我们参考了SimpleAdapter默认的构造函数的方法,创建了自定义的MyButtonAdapter类,在显示数据的同时,能够给每一行的按钮绑定点击事件。

3、弹出提示框

弹出提示框的代码很长,完全可以封装到一个方法中,简化代码。这里完整的列出来,目的就是体验一下设计思路。经过观察我们发现,这就是所谓的“链式编程”,可以通过连续的".",设置参数(控制显示效果)。

strings.xml:

 

[html]  view plain  copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <string name="positive">确定</string>  
  4.     <string name="negative">取消</string>  
  5. </resources>  

 

最终在pad上面的执行效果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值