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

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

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

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

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

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

activity_main.xml布局文件:

  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. <LinearLayout
  10. android:id="@+id/head"
  11. android:layout_width="match_parent"
  12. android:layout_height="wrap_content"
  13. android:orientation="horizontal" >
  14. <TextView
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:text="岗位名称"
  18. android:textSize="24sp"
  19. android:width="150dip" />
  20. <TextView
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"
  23. android:text="岗位数量"
  24. android:textSize="24sp"
  25. android:width="150dip" />
  26. <TextView
  27. android:layout_width="wrap_content"
  28. android:layout_height="wrap_content"
  29. android:text="发布日期"
  30. android:textSize="24sp"
  31. android:width="150dip" />
  32. <TextView
  33. android:layout_width="wrap_content"
  34. android:layout_height="wrap_content"
  35. android:text="岗位描述"
  36. android:textSize="24sp"
  37. android:width="550dip" />
  38. </LinearLayout>
  39. <ListView
  40. android:id="@id/android:list"
  41. android:layout_width="wrap_content"
  42. android:layout_height="wrap_content"
  43. android:layout_below="@+id/head" >
  44. </ListView>
  45. </RelativeLayout>

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

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

list_item.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="match_parent"
  5. android:orientation="horizontal" >
  6. <TextView
  7. android:id="@+id/name"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:textSize="24sp"
  11. android:width="150dip" />
  12. <TextView
  13. android:id="@+id/num"
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:textSize="24sp"
  17. android:width="150dip" />
  18. <TextView
  19. android:id="@+id/date"
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:textSize="24sp"
  23. android:width="150dip" />
  24. <TextView
  25. android:id="@+id/description"
  26. android:layout_width="wrap_content"
  27. android:layout_height="wrap_content"
  28. android:textSize="24sp"
  29. android:width="550dip" />
  30. <Button
  31. android:id="@+id/btn"
  32. android:layout_width="wrap_content"
  33. android:layout_height="wrap_content"
  34. android:focusable="false"
  35. android:focusableInTouchMode="false"
  36. android:text="报名"
  37. android:width="150dip"
  38. android:textSize="24sp" />
  39. </LinearLayout>

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

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

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

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

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

1、SQLite数据库的查询操作

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

2、ListView控件使用(重点)

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

3、弹出提示框

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

strings.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3. <string name="positive">确定</string>
  4. <string name="negative">取消</string>
  5. </resources>

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

Android开发系列之ListView的更多相关文章

  1. C# WinForm开发系列 - ListBox/ListView/Panel

    转自会飞的小猪文章 C# WinForm开发系列 - ListBox/ListView/Panel 在博客园看到了一篇博文,觉得很不错,就转载过来了.    包含自定义绘制的ListBox, 带拖动, ...

  2. Android 开发系列教程之(一)Android基础知识

    什么是Android Android一词最早是出现在法国作家维里耶德利尔·亚当1986年发表的<未来夏娃>这部科幻小说中,作者利尔·亚当将外表像人类的机器起名为Android,这就是And ...

  3. Android开发之去掉listview的点击效果,一行代码间接粗暴,解决你的问题。

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 Android开发之去掉listview的点击效果,一行代码间接粗暴,解决你的问题. 当你在用list ...

  4. [Android开发系列]IT博客应用

    1.关于坑 好吧,在此之前先来说一下,之前开的坑,恩,确实是坑,前面开的两个android开发教程的坑,对不起,实在是没什么动力了,不过源码都有的,大家可以参照github这个应用 https://g ...

  5. Android开发系列之按钮事件的4种写法

    经过前两篇blog的铺垫,我们今天热身一下,做个简单的例子. 目录结构还是引用上篇blog的截图. 具体实现代码: public class MainActivity extends Activity ...

  6. Android开发系列之SQLite

    上篇博客提到过SQLite,它是嵌入式数据库,由于其轻巧但功能强大,被广泛的用于嵌入式设备当中.后来在智能手机.平板流行之后,它作为文件型数据库,几乎成为了智能设备单机数据库的必选,可以随着安卓app ...

  7. Android开发系列之Android项目的目录结构

    今天开始正式学习Android开发的种种细节,首先从最基本的概念和操作学起. 首先看一下Android项目的目录结构. 这是我随便建立的一个test项目,我们重点关注一下几个方面的内容: 1.src目 ...

  8. Android开发系列之学习路线图

    通过前面的3篇博客已经简单的介绍了Android开发的过程并写了一个简单的demo,了解了Android开发的环境以及一些背景知识. 接下来这篇博客不打算继续学习Android开发的细节,先停一下,明 ...

  9. Android开发系列之搭建开发环境

    接触Android好久了,记得09年刚在中国大陆有点苗头的时候,我就知道了google有个Android,它是智能机操作系统.后来在Android出1.5版本之后,我第一时间下载了eclipse开发工 ...

随机推荐

  1. Tomcat部署web应用的三种方式

    原文:http://my.oschina.net/sunchp/blog/90235 一:相关概念 CATALINA_HOME:tomcat安装目录 CATALINA_BASE:tomcat工作目录 ...

  2. [React] Higher Order Components (replaces Mixins)

    Higher order components will allow you to apply behaviors to multiple React components. So the idea ...

  3. QUiLoader 动态加载.ui文件

    动态加载UI文件是指,用 Qt Designer 通过拖拽的方式生产.ui 文件.不用 uic工具把.ui 文件变成等价的 c++代码,而是在程序运行过程中需要用到UI文件时,用 QUiLoader ...

  4. iOS 图片加载框架- SDWebImage 解读

    在iOS的图片加载框架中,SDWebImage可谓是占据大半壁江山.它支持从网络中下载且缓存图片,并设置图片到对应的UIImageView控件或者UIButton控件.在项目中使用SDWebImage ...

  5. python--判断数据类型可不可变

    内存是一块空间,可以比喻成一个比较大的房子,定义一个变量就是在大房子中建立一个小房子,判断一个数据类型可不可变,就是看在这个这个大房子中有没有新建小房子,可以通过id来判断,如果id没有变化则是不可变 ...

  6. 0x80029C4A

    法将类型为“Microsoft.Office.Interop.Excel.ApplicationClass”的 COM 对象强制转换为接口类型“Microsoft.Office.Interop.Exc ...

  7. 如何实现XA式、非XA式Spring分布式事务

    Spring应用的几种事务处理机制 Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式.理想的实现取决于你的应用程序使用何种资源,你 ...

  8. IP地址子网掩码、主机数、子网掩码及主机段的算法

    http://wenku.baidu.com/view/2aa76cc6aa00b52acfc7ca6f.html很容易理解.

  9. LeetCode里有特色的问题存档

    002* Median of Two Sorted Arrays There are two sorted arrays A and B of size m and n respectively. F ...

  10. ubuntu下使用quick2wire控制RespberryPi2的I2C

    首先,开启树莓派的I2C驱动: 查看I2C驱动是否已经被加载:ls /dev -l | grep i2c,如果有形如 i2c-x 的显示结果表明驱动已经加载,否则驱动没有加载,需要进行如下操作: 修改 ...