上篇博客解决了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. Android控件之ListView的使用

    ListView是Android当中一个非常常用的数据显示控件. 第一种可以使用List<HashMap<String , Object>>,作为适配器的数据源来显示要显示的数 ...

  2. [Android Pro] android控件ListView顶部或者底部也显示分割线

    reference to  :  http://blog.csdn.net/lovexieyuan520/article/details/50846569 在默认的Android控件ListView在 ...

  3. UIAutomator定位Android控件的方法

    UIAutomator各种控件定位的方法. 1. 背景 使用SDK自带的NotePad应用,尝试去获得在NotesList那个Activity里的Menu Options上面的那个Add note菜单 ...

  4. 【转】UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)

    原文地址:http://blog.csdn.net/zhubaitian/article/details/39777951 在本人之前的一篇文章<<Appium基于安卓的各种FindEle ...

  5. UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)

    在本人之前的一篇文章<<Appium基于安卓的各种FindElement的控件定位方法实践和建议>>第二章节谈到Appium可以通过使用UIAutomator的方法去定位And ...

  6. Android控件GridView之仿支付宝钱包首页带有分割线的GridView九宫格的完美实现

    Android控件GridView之仿支付宝钱包首页带有分割线的GridView九宫格的完美实现 2015-03-10 22:38 28419人阅读 评论(17) 收藏 举报  分类: Android ...

  7. Android控件介绍

    1. 介绍 Android控件大多位于android.widget, android.view.View为他们的父类对于Dialog系列, android.app.Dialog为父类 Android的 ...

  8. Android控件RecyclerView的基本用法

    Android控件RecyclerView的基本用法 转 https://www.jianshu.com/p/e71a4b73098f   github: https://github.com/Cym ...

  9. Android 控件架构及View、ViewGroup的测量

    附录:示例代码地址 控件在Android开发的过程中是必不可少的,无论是我们在使用系统控件还是自定义的控件.下面我们将讲解一下Android的控件架构,以及如何实现自定义控件. 1.Android控件 ...

随机推荐

  1. .net网站建设页面提交后css失效的问题

    问题描述:.net网站建设在提交后出现css部分失效,如div位置,字体大小. 问题解决:原因是,过去的提示语句我们一律使用了Response.write("<script>al ...

  2. Android使用http协议与服务器通信

    网上介绍Android上http通信的文章很多,不过大部分只给出了实现代码的片段,一些注意事项和如何设计一个合理的类用来处理所有的http请求以及返回结果,一般都不会提及.因此,自己对此做了些总结,给 ...

  3. Android : Your APK does not seem to be designed for tablets.

    1. 解决办法: Add these config in AndroidManifest.xml <supports-screens android:smallScreens="tru ...

  4. 阿里云提出的漏洞(Phpcms V9某处逻辑问题导致getshell漏洞解决方法)的问题

    最近从阿里云云盾检测流出来的,相比使用阿里云服务器的朋友已经收到漏洞提醒:Phpcms V9某处逻辑问题导致getshell漏洞解决方法,这个漏洞怎么办呢?CMSYOU在这里找到针对性解决办法分享给大 ...

  5. Thinkphp 模板中使用自定义函数的方法

    1.number_format {$number|number_format=2}   千分位,保留两位小数 2.round {$number|round=2}   四舍五入保留两位小数

  6. Python--异常处理--12

    Python 异常处理 原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/ python提供了两个非常重要的功能来处理python程序在运行中出现的 ...

  7. [Converge] Backpropagation Algorithm

    Ref: CS231n Winter 2016: Lecture 4: Backpropagation Ref: How to implement a NN:中文翻译版本 Ref: Jacobian矩 ...

  8. DB索引、索引覆盖、索引优化

    ###########索引########### @see   http://mp.weixin.qq.com/s/4W4iVOZHdMglk0F_Ikao7A 聚集索引(clustered inde ...

  9. python是c语言开发的

    python是c语言开发的. #c语言,没有字符串:字符串使用字符组表现   hello —五个字符 字符数组 [’h’,’e’,…’o’]   所以python中如果对一个字符串进行修改,就是在内存 ...

  10. NTP服务器时间集群借节点之间同步

    1.三个节点时间同步,cdh1,cdh2,cdh3 2.做法:cdh1从网络时间同步,然后cdh2和cdh3从cdh1节点同步 3.安装与自启动设置 yum install ntp 按上面的安装方式在 ...