本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020
通过之前的10节,已实现了记事本的大部分功能,有添加拍照,添加照片,添加录音,添加绘图,添加手写,另外细心的可以发现,底部菜单还有一个更多的选项,这个以后再实现,用于扩展记事本的功能。
这节就来为我们的记事本添加数据库支持,这样,就可以在添加记事后将其保存在数据库中,方便下次浏览,修改,删除等。
先看效果图:
三张图片分别演示了保存记事,查看记事,删除记事。
对于数据库而言,无非就是涉及到数据库的创建,增删改查。
为了将数据库的操作封装起来,单独写了一个类,如下:
DatabaseOperation.java
import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.widget.Toast; public class DatabaseOperation { private SQLiteDatabase db; private Context context; public DatabaseOperation(Context context,SQLiteDatabase db) { this.db = db; this.context = context; } //数据库的打开或创建 public void create_db(){ //创建或打开数据库 db = SQLiteDatabase.openOrCreateDatabase(context.getFilesDir().toString()+ "/mynotes.db3", null); db.execSQL( "DROP TABLE IF EXISTS studentScore"); if(db == null){ Toast.makeText(context, "数据库创建不成功",Toast.LENGTH_LONG).show(); } //Toast.makeText(context,"数据库创建成功",Toast.LENGTH_LONG).show(); //创建表 db.execSQL( "create table if not exists notes(_id integer primary key autoincrement," + "title text," + "context text," + "time varchar(20))"); } public void insert_db(String title,String text,String time){ if(text.isEmpty()){ Toast.makeText(context, "各字段不能为空", Toast.LENGTH_LONG).show(); } else{ db.execSQL( "insert into notes(title,context,time) values('"+ title+ "','"+ text+ "','"+time+ "');"); //Toast.makeText(context, "插入成功", Toast.LENGTH_LONG).show(); } } public void update_db(String title,String text,String time,int item_ID){ if( text.isEmpty()){ Toast.makeText(context, "各字段不能为空", Toast.LENGTH_LONG).show(); } else{ //String sql = "update main set class1='" + class1 + "',class2='" + class2 + "',class3='" + class4 + "',class4='" + class4 + "'where days='" + days + "';"; db.execSQL( "update notes set context='"+text+ "',title='"+title+ "',time='"+time+ "'where _id='" + item_ID+ "'"); //Toast.makeText(context, "修改成功", Toast.LENGTH_LONG).show(); } } public Cursor query_db(){ Cursor cursor = db.rawQuery( "select * from notes", null); return cursor; } public Cursor query_db(int item_ID){ Cursor cursor = db.rawQuery( "select * from notes where _id='"+item_ID+ "';", null); return cursor; } public void delete_db(int item_ID){ db.execSQL( "delete from notes where _id='" + item_ID+ "'"); //Toast.makeText(context, "删除成功", Toast.LENGTH_LONG).show(); } //关闭数据库 public void close_db(){ db.close(); } } 有了这些数据库的相关操作,下面就开始实现保存记事,修改记事,删除记事,查询记事的功能。当编辑好一个记事时,这时点击顶部的保存按钮,就将所写的记事插入到数据库中,当然了,如果记事里面有图片,录音等,并没有图片,录音本身存储到数据库,而是将其所在路径存储在数据库中,等到再次查看时,再从数据库中读取,并根据所保存的路径取出源文件。
保存记事的思想就是取出EditText中的内容,并从中截取前一部分作为该记事的标题,以及同时也保存了添加记事的时间。
主要代码为:
//取得EditText中的内容 String context = et_Notes.getText().toString(); if(context.isEmpty()){ Toast.makeText(AddActivity. this, "记事为空!", Toast.LENGTH_LONG).show(); } else{ //取得当前时间 SimpleDateFormat formatter = new SimpleDateFormat ( "yyyy-MM-dd HH:mm"); Date curDate = new Date(System.currentTimeMillis()); //获取当前时间 String time = formatter.format(curDate); //截取EditText中的前一部分作为标题,用于显示在主页列表中 String title = getTitle(context); //打开数据库 dop.create_db(); //判断是更新还是新增记事 if(editModel.equals( "newAdd")){ //将记事插入到数据库中 dop.insert_db(title,context,time); } //如果是编辑则更新记事即可 else if(editModel.equals( "update")){ dop.update_db(title,context,time,item_Id); } dop.close_db(); //结束当前activity AddActivity. this.finish(); } 其中, getTitle()函数就是为了截取记事正文的前15字作为该记事的标题;editModel表示当前是新增记事还是修改记事。getTitle()如下: //截取EditText中的前一部分作为标题,用于显示在主页列表中 private String getTitle(String context){ //定义正则表达式,用于匹配路径 Pattern p=Pattern.compile( "/([^\\.]*)\\.\\w{3}"); Matcher m=p.matcher(context); StringBuffer strBuff = new StringBuffer(); String title = ""; int startIndex = 0; while(m.find()){ //取出路径前的文字 if(m.start() > 0){ strBuff.append(context.substring(startIndex, m.start())); } //取出路径 String path = m.group().toString(); //取出路径的后缀 String type = path.substring(path.length() - 3, path.length()); //判断附件的类型 if(type.equals( "amr")){ strBuff.append( "[录音]"); } else{ strBuff.append( "[图片]"); } startIndex = m.end(); //只取出前15个字作为标题 if(strBuff.length() > 15){ //统一将回车,等特殊字符换成空格 title = strBuff.toString().replaceAll( "\r|\n|\t", " "); return title; } } strBuff.append(context.substring(startIndex, context.length())); //统一将回车,等特殊字符换成空格 title = strBuff.toString().replaceAll( "\r|\n|\t", " "); return title; } 这里主要是用到了正则表达式,用于匹配是普通文字还是图片录音等,如果是图片录音,则在标题中显然图片录音文字即可,这里还用到了一个技巧,就是return 的上一句,目的就是为了将标题中的回车等特殊字符统一换成空格。在保存了记事后,当然就要从数据库取出,并以原来的格式显示给用户。设想一下,在新增了记事后,返回主页或者重新进入主页,就应该看到当前已保存的记事列表,所以在主页的Activity中应该放置一个列表(ListView)用于显示从数据库中取出的数据。当点击列表的项目时,就应该打开查看该记事的详细内容了。
因为在保存记事时已经截取了一部分作为标题,所以在主页记事列表上只显示标题,时间,而不显然详细内容。主要代码下:
private SQLiteDatabase db; private DatabaseOperation dop; private ListView lv_notes; ...... //数据库操作 dop = new DatabaseOperation( this, db); lv_notes = (ListView)findViewById(R.id.lv_notes); //显示记事列表 showNotesList(); //为记事列表添加监听器 lv_notes.setOnItemClickListener( new ItemClickEvent());其中,showNotesList()就是用来显然记事列表的,如下:
//显示记事列表 private void showNotesList(){ //创建或打开数据库 dop.create_db(); Cursor cursor = dop.query_db(); SimpleCursorAdapter adapter = new SimpleCursorAdapter( this, R.layout.note_item, cursor, new String[]{ "_id", "title", "time"}, new int[]{R.id.tv_note_id,R.id.tv_note_title,R.id.tv_note_time}); lv_notes.setAdapter(adapter); dop.close_db(); }上面只实现了浏览记事列表的功能,那么点击列表项目,自然就是查看或修改记事的详细内容了,所以为列表添加单击事件,并在其监听器中实现从数据库读取相应的记事内容,并显示,如下:
//记事列表单击监听器 class ItemClickEvent implements OnItemClickListener{ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { tv_note_id = (TextView)view.findViewById(R.id.tv_note_id); int item_id = Integer.parseInt(tv_note_id.getText().toString()); Intent intent = new Intent(MainActivity. this,AddActivity.class); intent.putExtra( "editModel", "update"); intent.putExtra( "noteId", item_id); startActivity(intent); } } 这样,当单击一个列表项时,就会新打开一个activity,用于显示记事的详细内容,这里依然用的是新增记事Activity,这样做的好处就是在查看记事的同时,也可以修改,这也是大多数记事软件所采用的方法,而且,也能过intent将一些信息传递给AddActivity,其中editModel是编辑模式,因为这里是查看或者修改,所以当再次点击保存时,就更新原有的记事即可,并不是又新增加一条记事;noteId是为了让AddActivity知道该读取数据库的中那一条数据。相应的,要在AddActivity里添加代码取出数据并显示,主要代码如下: //加载数据 private void loadData(){ //如果是新增记事模式,则将editText清空 if(editModel.equals( "newAdd")){ et_Notes.setText( ""); } //如果编辑的是已存在的记事,则将数据库的保存的数据取出,并显示在EditText中 else if(editModel.equals( "update")){ tv_title.setText( "编辑记事"); dop.create_db(); Cursor cursor = dop.query_db(item_Id); cursor.moveToFirst(); //取出数据库中相应的字段内容 String context = cursor.getString(cursor.getColumnIndex( "context")); //定义正则表达式,用于匹配路径 Pattern p=Pattern.compile( "/([^\\.]*)\\.\\w{3}"); Matcher m=p.matcher(context); int startIndex = 0; while(m.find()){ //取出路径前的文字 if(m.start() > 0){ et_Notes.append(context.substring(startIndex, m.start())); } SpannableString ss = new SpannableString(m.group().toString()); //取出路径 String path = m.group().toString(); //取出路径的后缀 String type = path.substring(path.length() - 3, path.length()); Bitmap bm = null; Bitmap rbm = null; //判断附件的类型,如果是录音文件,则从资源文件中加载图片 if(type.equals( "amr")){ bm = BitmapFactory.decodeResource(getResources(), R.drawable.record_icon); //缩放图片 rbm = resize(bm, 200); } else{ //取出图片 bm = BitmapFactory.decodeFile(m.group()); //缩放图片 rbm = resize(bm, 480); } //为图片添加边框效果 rbm = getBitmapHuaSeBianKuang(rbm); System.out.println(rbm.getWidth()+ "-------"+rbm.getHeight()); ImageSpan span = new ImageSpan( this, rbm); ss.setSpan(span, 0, m.end() - m.start(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); et_Notes.append(ss); startIndex = m.end(); } //将最后一个图片之后的文字添加在TextView中 et_Notes.append(context.substring(startIndex,context.length())); dop.close_db(); } } 这里同样是用到了正则表达式,因为要识别路径。通过这个方法,在每次打开AddActivity时调用该方法,即能适用于新增记事,也可以用于修改记事。删除记事的实现还是在主页Activity中实现,当长按列表项目时,弹出操作选择,共有两个,一个是编辑,一个是删除,这里的编辑是和单击列表项的查看记事的功能一样,主要是删除,当选中了删除时,就将相应的记事条目从数据库中删除,并刷新列表。主要代码如下:
...... //为记事列表添加长按事件 lv_notes.setOnItemLongClickListener( new ItemLongClickEvent()); ...... //记事列表长按监听器 class ItemLongClickEvent implements OnItemLongClickListener{ @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { tv_note_id = (TextView)view.findViewById(R.id.tv_note_id); int item_id = Integer.parseInt(tv_note_id.getText().toString()); simpleList(item_id); return true; } } //简单列表对话框,用于选择操作 public void simpleList(final int item_id){ AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( this,R.style.custom_dialog); alertDialogBuilder.setTitle( "选择操作"); alertDialogBuilder.setIcon(R.drawable.ic_launcher); alertDialogBuilder.setItems(R.array.itemOperation, new android.content.DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch(which){ //编辑 case 0 : Intent intent = new Intent(MainActivity. this,AddActivity.class); intent.putExtra( "editModel", "update"); intent.putExtra( "noteId", item_id); startActivity(intent); break; //删除 case 1 : dop.create_db(); dop.delete_db(item_id); dop.close_db(); //刷新列表显示 lv_notes.invalidate(); showNotesList(); break; } } }); alertDialogBuilder.create(); alertDialogBuilder.show(); } 以上,就实现了记事的保存,修改,删除的功能,到此,记事本的功能已基本完成,剩下的就是后续的完善与优化,以及新增功能了。