上篇博客解决了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. Java路径操作具体解释

    1.基本概念的理解 绝对路径:绝对路径就是你的主页上的文件或文件夹在硬盘上真正的路径.(URL和物理路径)比如: C:\xyz\test.txt 代表了test.txt文件的绝对路径.http://w ...

  2. MFC——从实现角度分析微云界面

    在云计算时代之风吹来,很多互联网公司都在建云,提出云盘.云储存.云平台.云空间等等,骤然间,天下皆云.云是啥?有用户量,就有云,没有用户量,你的系统,你的云,也就是一朵白云. 最近研究了下微云的界面, ...

  3. android学习日记03--常用控件ListView

    常用控件 8.ListView 列表视图,比如游戏的排行榜.列表数据可以根据屏幕大小自适应 列表的显示需要三个元素: a.ListVeiw:用来展示列表的View. b.适配器:用来把数据映射到Lis ...

  4. (转)如何在JavaScript与ActiveX之间传递数据2

    本文研究如何在JS等脚本语言与ActiveX控件之间通信,如何传递各种类型的参数,以及COM的IDispatch接口.使用类似的方法,可以推广到其他所有脚本型语言,如LUA,AutoCad等.本文将研 ...

  5. careercup-C和C++ 13.6

    13.6 基类的析构函数为何要声明为virtual? 解答: 用对象指针来调用一个函数,有以下两种情况: 如果是虚函数,会调用派生类中的版本. 如果是非虚函数,会调用指针所指类型的实现版本. 析构函数 ...

  6. .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二)

    .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二) .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (一) 上一篇主 ...

  7. linux实例 批量修改图片文件名

    1.如10.11一批这样的目录,10.11 10.12等等 然后里面的图片.jpg文件要修改成对应的日期.jpg,也就是说 编程1011.jpg这样的文件名 示例如下: #!/bin/bashfor ...

  8. 【转】 使用Beaglebone Black的PRU(三)——实现高达100MHz的GPIO输出

    友情提示:请先按照本系列(一)(二)的说明安装PRU工具并跑通hello world再继续按本文操作. PRU操作GPIO有很多种方式,本系列之(二)中的是一种,但最快速的方式是通过直接“写”r30和 ...

  9. 关于iOS自定义返回按钮右滑返回手势失效的解决:

    在viewDidLoad方法里面添加下面这一句代码即可 self.navigationController.interactivePopGestureRecognizer.delegate=(id)s ...

  10. (转)fastdfs_v4.07 / 实现多服务器

    http://my.oschina.net/shking/blog/165326 自己闲着没事,在小黑上虚拟了 4 个 centos 64 的系统,用来安装分布式 fastdfs . nginx 负载 ...