前几天写了一个Android记事本小程序,现在记录一下。

项目源码地址在文章最后。

考虑到是记事本小程序,记录的内容只有文字,而且内容不会太长,所以选择使用SQLite数据库,数据存放在用户的手机上。

牵涉到数据库,那自然是一个实体。先设计实体数据表:DBHelper.java

package com.ikok.notepad.DBUtil;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;/*** Created by Anonymous on 2016/3/24.*/
public class DBHelper extends SQLiteOpenHelper {/*** 创建笔记表*/private static final String CREATE_NOTE = "create table Note(" +"id integer primary key autoincrement," +"content text," +"time text)";private Context mContext;public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {super(context, name, factory, version);mContext = context;}@Overridepublic void onCreate(SQLiteDatabase sqLiteDatabase) {sqLiteDatabase.execSQL(CREATE_NOTE);
//        Toast.makeText(mContext,"Created",Toast.LENGTH_SHORT).show();}@Overridepublic void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {}
}

创建完数据表后,自然需要操作数据库,CRUD数据,我把所有跟数据库有关的操作封装在一起: NoteDB.java

package com.ikok.notepad.DBUtil;import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;import com.ikok.notepad.Entity.Note;import java.util.ArrayList;
import java.util.List;/*** Created by Anonymous on 2016/3/24.*/
public class NoteDB {public static final String DB_NAME = "notepad";public static final int VERSION = 1;private static NoteDB mNoteDB;private SQLiteDatabase db;public NoteDB(Context context) {DBHelper dbHelper = new DBHelper(context,DB_NAME,null,VERSION);db = dbHelper.getWritableDatabase();}/*** 获取 NoteDB 的实例* @param context* @return*/public synchronized static NoteDB getInstance(Context context){if (mNoteDB == null){mNoteDB = new NoteDB(context);}return mNoteDB;}public void saveNote(Note note){if (note != null) {ContentValues values = new ContentValues();values.put("content", note.getContent());values.put("time", note.getTime());db.insert("Note", null, values);}}public List<Note> loadNotes(){List<Note> noteList = new ArrayList<Note>();/*** 先按时间降序排列,再按id降序排列*/Cursor cursor = db.query("Note",null,null,null,null,null,"time desc,id desc");if (cursor.moveToNext()){do {Note note = new Note();note.setId(cursor.getInt(cursor.getColumnIndex("id")));note.setContent(cursor.getString(cursor.getColumnIndex("content")));note.setTime(cursor.getString(cursor.getColumnIndex("time")));noteList.add(note);} while (cursor.moveToNext());}return noteList;}public Note loadById(int id){Note note = null;Cursor cursor = db.query("Note",null,"id = " + id,null,null,null,null);if (cursor.moveToNext()){note = new Note();note.setContent(cursor.getString(cursor.getColumnIndex("content")));note.setTime(cursor.getString(cursor.getColumnIndex("time")));}return note;}public void deleteById(Integer id){db.delete("Note","id = " + id,null);}public void deleteAllNote(){db.delete("Note", null, null);}public void updateById(String noteTime, String noteContent, int noteId){ContentValues values = new ContentValues();values.put("content",noteContent);values.put("time",noteTime);db.update("Note",values,"id = " + noteId,null);}}

设计完数据库后,与数据库对应的需要一个实体类: Note.java

package com.ikok.notepad.Entity;import java.io.Serializable;/*** Created by Anonymous on 2016/3/24.*/
public class Note implements Serializable {private int id;private String content;private String time;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public String getTime() {return time;}public void setTime(String time) {this.time = time;}
}

接下来进行App主页的设计: main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/repeat_bg"android:orientation="vertical"><TextViewandroid:id="@+id/app_title"android:layout_width="match_parent"android:layout_height="40dp"android:textSize="16sp"android:gravity="center"android:text="@string/app_title"android:textColor="#333"/><ListViewandroid:id="@+id/listview"android:descendantFocusability="blocksDescendants"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"></ListView><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="40dp"><ImageButtonandroid:id="@+id/about_btn"android:src="@drawable/about_me"android:layout_alignParentLeft="true"android:paddingLeft="20dp"android:background="#00ffffff"android:scaleType="center"android:layout_marginTop="4dp"android:layout_width="52dp"android:layout_height="32dp" /><TextViewandroid:id="@+id/note_num"android:layout_width="wrap_content"android:layout_height="30dp"android:paddingTop="2dp"android:textSize="18sp"android:textColor="#333"android:layout_centerInParent="true"android:text="@string/app_title"/><ImageButtonandroid:id="@+id/write_btn"android:src="@drawable/write_btn"android:layout_alignParentRight="true"android:paddingRight="20dp"android:background="#00ffffff"android:scaleType="center"android:layout_marginTop="4dp"android:layout_width="52dp"android:layout_height="32dp" /></RelativeLayout></LinearLayout>

具体效果如下(图标懒得去改颜色了):

左边的是一个关于App的按钮,右边的新建记事本的按钮。

因为主页需要显示已经记录的内容,所以我选择用ListView去显示。用到ListView,则与之对应的是要一个数据源,一个适配器。所以我为每一条子项设计了一个样式,去让它左边显示创建或更新的时间,右边显示内容。如下:list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:minHeight="50dp"android:orientation="horizontal"><TextViewandroid:id="@+id/show_time"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"android:paddingLeft="10dp"android:textColor="#333"android:textSize="16sp" /><TextViewandroid:id="@+id/show_content"android:layout_width="0dp"android:layout_weight="1"android:layout_height="match_parent"android:textSize="16sp"android:paddingLeft="20dp"android:textColor="#333"android:paddingTop="14dp"android:singleLine="true" /></LinearLayout>

创建好了ListView,接下来为它准备适配器:MyAdapter.java

package com.ikok.notepad.Util;import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;import com.ikok.notepad.Entity.Note;
import com.ikok.notepad.R;import java.util.List;/*** Created by Anonymous on 2016/3/24.*/
public class MyAdapter extends BaseAdapter {private List<Note> noteList;private LayoutInflater mInflater;private Context mContext;private int index;public MyAdapter(Context context,List<Note> noteList,ListView listView) {this.mInflater = LayoutInflater.from(context);this.noteList = noteList;this.mContext = context;}@Overridepublic int getCount() {return noteList.size();}@Overridepublic Object getItem(int i) {return noteList.get(i);}@Overridepublic long getItemId(int i) {return i;}@Overridepublic View getView(int i, View convertView, ViewGroup viewGroup) {ViewHolder viewHolder = null;if (convertView == null){viewHolder = new ViewHolder();convertView = mInflater.inflate(R.layout.list_item, null);viewHolder.mTime = (TextView) convertView.findViewById(R.id.show_time);viewHolder.mContent = (TextView) convertView.findViewById(R.id.show_content);convertView.setTag(viewHolder);} else {viewHolder = (ViewHolder) convertView.getTag();}viewHolder.mTime.setText(noteList.get(i).getTime());viewHolder.mContent.setText(noteList.get(i).getContent());index = i;//        convertView.setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View view) {
//                Intent intent = new Intent(mContext,UpdateOrReadActivity.class);Bundle bundle = new Bundle();bundle.putSerializable("note_item",noteList.get(index));intent.putExtras(bundle);
//                intent.putExtra("note_id",noteList.get(index).getId());
//                Log.d("Anonymous","备忘录ID:"+noteList.get(index).getId());
//                mContext.startActivity(intent);
//                Log.d("Anonymous","执行了适配器里的点击事件");
//            }
//        });return convertView;}class ViewHolder{public TextView mTime;public TextView mContent;}
}

这里采用了使用ViewHolder,来使ListView滚动的时候不必每次重新创建对象,提升性能。

创建好了ListView,准备好了适配器,接下来要为ListView准备数据源,而这数据源是要从数据库读出来的。但是数据库操作和网络访问等都是属于耗时操作,如果用主UI线程去执行响应操作的话,很可能会出现ANR现象,所以这里我用AsyncTask去执行数据库操作。主Activity代码如下:MainActivity.java

package com.ikok.notepad.Activity;import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;import com.ikok.notepad.DBUtil.NoteDB;
import com.ikok.notepad.Entity.Note;
import com.ikok.notepad.R;
import com.ikok.notepad.Util.DeleteAsyncTask;
import com.ikok.notepad.Util.MyAdapter;import java.util.ArrayList;
import java.util.List;/*** Created by Anonymous on 2016/3/24.*/
public class MainActivity extends Activity {/*** 布局控件*/private TextView mTitle;private TextView mNoteNum;private ImageButton mWrite;private ListView mNoteListView;private ImageButton mAbout;/*** 数据库实例,数据源*/private List<Note> mNoteList = new ArrayList<Note>() ;private NoteDB mNoteDB;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.main_activity);initView();new NewAsyncTask().execute();initEvent();}private void initEvent() {/*** 新写一条备忘录*/mWrite.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Intent intent = new Intent(MainActivity.this, AddNoteActivity.class);startActivity(intent);}});/*** 修改或查看一条已有的备忘录*/mNoteListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {Note note = (Note) adapterView.getItemAtPosition(i);
//                Log.d("Anonymous", "点击ListView获取的note id: " + note.getId());Intent intent = new Intent(MainActivity.this, UpdateOrReadActivity.class);intent.putExtra("note_id", note.getId());startActivity(intent);}});/*** listview长按删除*/mNoteListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {@Overridepublic boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {final Note note = (Note) parent.getItemAtPosition(position);
//                Log.d("Anonymous", "长按ListView获取的note id: " + note.getId());/*** 长按提示是否删除*/new AlertDialog.Builder(MainActivity.this).setTitle("提示").setMessage("真的要删除这条记录吗?").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {new DeleteAsyncTask(mNoteDB).execute(note.getId());new NewAsyncTask().execute();}}).setNegativeButton("取消", null).show();return true;}});/*** 关于自己*/mAbout.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(MainActivity.this,AboutActivity.class);startActivity(intent);}});}public void initView() {/*** 布局控件初始化*/mTitle = (TextView) findViewById(R.id.app_title);// 画TextView文字下的下划线
//        mTitle.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);mNoteNum = (TextView) findViewById(R.id.note_num);mWrite = (ImageButton) findViewById(R.id.write_btn);mNoteListView = (ListView) findViewById(R.id.listview);mAbout = (ImageButton) findViewById(R.id.about_btn);/*** 获取数据库实例*/mNoteDB = NoteDB.getInstance(this);}/*** 异步加载备忘录*/class NewAsyncTask extends AsyncTask<Void,Void,List<Note>>{@Overrideprotected List<Note> doInBackground(Void... voids) {mNoteList = mNoteDB.loadNotes();return mNoteList;}@Overrideprotected void onPostExecute(List<Note> notes) {super.onPostExecute(notes);/*** 设置适配器,绑定适配器*/MyAdapter myAdapter = new MyAdapter(MainActivity.this,notes,mNoteListView);mNoteListView.setAdapter(myAdapter);/*** 更新备忘录记录数*/int temp = mNoteList.size();mNoteNum.setText("共 " + temp + " 条备忘录");}}/*** 当活动恢复时,刷新listview和备忘录记录数*/@Overrideprotected void onResume() {super.onResume();new NewAsyncTask().execute();}}

在上面的代码中,我新建了一个 NewAsyncTask 类去继承 AsyncTask,去执行从数据库读取数据的操作,在onPostExecute()方法中,去更新UI,比如显示ListView中的数据,一下页面底部中间有几条数据等。还有我考虑了新建记事本的话,是另外一个Activity。当从另外的Activity返回到主Activity时,主页面应该再刷新一次,刷新数据和显示,所以我在onResume()方法中调用了  NewAsyncTask().execute() 方法,当活动恢复时刷新显示。

接下来是新建记事本的Activity,布局如下:write_note.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/screen_view"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/repeat_bg"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="40dp"><ImageButtonandroid:id="@+id/back_btn"android:src="@drawable/back_btn"android:layout_alignParentLeft="true"android:paddingLeft="5dp"android:background="#00ffffff"android:scaleType="center"android:layout_marginTop="6dp"android:layout_width="52dp"android:layout_height="32dp" /><TextViewandroid:id="@+id/complete_btn"android:layout_alignParentRight="true"android:paddingTop="10dp"android:paddingRight="10dp"android:textSize="18sp"android:textColor="#ec6d51"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/complete"/></RelativeLayout><EditTextandroid:id="@+id/note_content"android:layout_width="match_parent"android:layout_height="wrap_content"android:paddingLeft="10dp"android:paddingRight="10dp"android:textColor="#333"android:textCursorDrawable="@null"android:background="@null"/></LinearLayout>

具体效果如下:

新建记事本的Activity如下:AddNoteActivity.java

package com.ikok.notepad.Activity;import android.app.Activity;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;import com.ikok.notepad.DBUtil.NoteDB;
import com.ikok.notepad.Entity.Note;
import com.ikok.notepad.R;import java.text.SimpleDateFormat;
import java.util.Date;/*** Created by Anonymous on 2016/3/24.*/
public class AddNoteActivity extends Activity {/*** 布局控件*/private TextView mComplete;private ImageButton mBackBtn;private EditText mContent;/*** 备忘录数据*/private String noteTime;private String noteContent;/*** 数据库*/private NoteDB mNoteDB;private Note note;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.write_note);initView();initEvent();}private void initView() {/*** 布局控件初始化*/mComplete = (TextView) findViewById(R.id.complete_btn);mBackBtn = (ImageButton) findViewById(R.id.back_btn);mContent = (EditText) findViewById(R.id.note_content);/*** 获取数据库实例*/mNoteDB = NoteDB.getInstance(this);}/*** 事件处理*/private void initEvent() {/*** 返回上一级菜单,如果有内容,提示是否保存* 是、保存,销毁活动;否,直接销毁活动*/mBackBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {saveDataOrNot();}});/*** 完成按钮,保存备忘录到数据库*/mComplete.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {if (!mContent.getText().toString().equals("")){new AddAsyncTask().execute();finish();} else {finish();}}});}/*** 根据是否有内容,提示保存*/private void saveDataOrNot() {if (!mContent.getText().toString().trim().equals("")) {new AlertDialog.Builder(AddNoteActivity.this).setTitle("提示").setMessage("需要保存您编辑的内容吗?").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {new AddAsyncTask().execute();finish();}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {finish();}}).show();} else {finish();}}/*** 添加数据到数据库*/class AddAsyncTask extends AsyncTask<Void,Void,Void>{@Overrideprotected Void doInBackground(Void... voids) {mNoteDB.saveNote(note);return null;}@Overrideprotected void onPreExecute() {super.onPreExecute();/*** 记录数据*/SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm");Date date = new Date(System.currentTimeMillis());noteTime = sdf.format(date);noteContent = mContent.getText().toString();note = new Note();note.setTime(noteTime);note.setContent(noteContent);}@Overrideprotected void onPostExecute(Void aVoid) {super.onPostExecute(aVoid);Toast.makeText(AddNoteActivity.this, "保存成功!", Toast.LENGTH_SHORT).show();}}/*** 按返回键,有内容时,提示保存*/@Overridepublic void onBackPressed() {saveDataOrNot();}
}

新建记事本,插入数据到数据库,如从数据库读取数据一样,都是耗时操作,所以我还是用了AsyncTask,在 onPreExecute()方法中,先获取到系统当前时间,进行格式化,存储下来,把输入的文本存储下来,然后再 doInBackground()去保存数据。这里我考虑了,用户输入了内容,但是没有保存,在顶部的返回键或者系统的返回键的处理事件中都加了判断。如果文本为空,空格也算空,则不保存,直接退出当前Activity,如果有内容,则弹出对话框提示用户是否保存,是则保存,否则不保存,退出当前活动。

接下来是查看或修改一条记事本了,布局我是直接复用新建记事本的布局。因为没有区别 - -

接下来是查看或修改一条记事本的Activity了,之前,我想的是点击一条记事本,则进入这条记事本,把这条记事本直接显示在页面上,用户直接在内容最后进行编辑。所以这里需要一个子项点击事件。我在MainActivity里已经写了,先获取当前点击的这一项的对象,这里我费了好多时间,我不知道点击这一项的时候,怎么把该项的对象读取出来。最后自己查看源码,查API,看到参数中AdapterView是个泛型,我试着从它着手,把它强转成Note对象,然后试试获取id,没想到就成了。 - -

所以,我获取了当前点击的item中的Note对象的id,把它放在Intent中,带着这个参数去开启活动。

这里,查看或修改一条记事本的Activity正式开始了,如下:UpdateOrReadActivity.java

package com.ikok.notepad.Activity;import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;import com.ikok.notepad.DBUtil.NoteDB;
import com.ikok.notepad.Entity.Note;
import com.ikok.notepad.R;
import com.ikok.notepad.Util.DeleteAsyncTask;import java.text.SimpleDateFormat;
import java.util.Date;/*** Created by Anonymous on 2016/3/24.*/
public class UpdateOrReadActivity extends Activity {/*** 布局控件*/private TextView mComplete;private ImageButton mBackBtn;private EditText mContent;private LinearLayout mScreen;/*** 备忘录数据*/private int noteId;private String noteTime;private String noteContent;private String originData;/*** 数据库*/private NoteDB mNoteDB;private static Note note;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.write_note);/*** 获取传递过来的note对象*/Intent intent = getIntent();// 传递Note对象,必须要Note实体实现Serializable
//        note = (Note) intent.getSerializableExtra("note_item");noteId = intent.getIntExtra("note_id",0);Log.d("Anonymous", "传递后的备忘录ID:" + noteId);initView();/*** 加载显示数据*/new LoadAsyncTask().execute();initEvent();}private void initView() {/*** 布局控件初始化*/mComplete = (TextView) findViewById(R.id.complete_btn);mBackBtn = (ImageButton) findViewById(R.id.back_btn);mContent = (EditText) findViewById(R.id.note_content);mScreen = (LinearLayout) findViewById(R.id.screen_view);/*** 获取数据库实例*/mNoteDB = NoteDB.getInstance(this);}private void initEvent() {/*** 返回上一级菜单,直接销毁当前活动*/mBackBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {updateDataOrNot();}});/*** 完成按钮,修改备忘录到数据库*/mComplete.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {if (mContent.getText().toString().trim().equals("")){
//                    Log.d("Anonymous","进入判断为空函数");new DeleteAsyncTask(mNoteDB).execute(noteId);finish();} else if (mContent.getText().toString().equals(originData)) {finish();} else {
//                    Log.d("Anonymous","进入判断不为空函数");new UpdateAsyncTask().execute();
//                    Toast.makeText(UpdateOrReadActivity.this, "修改成功!", Toast.LENGTH_SHORT).show();finish();}}});/*** 点击屏幕空白区域,EditText选中*/}/*** 根据id从数据库读数据的异步任务*/class LoadAsyncTask extends AsyncTask<Void,Void,Note>{@Overrideprotected Note doInBackground(Void... voids) {note = mNoteDB.loadById(noteId);return note;}@Overrideprotected void onPostExecute(Note note) {super.onPostExecute(note);/*** 根据传递进来的Note显示备忘录内容,并把光标移动到最后* 记录最初的文本内容*/originData = note.getContent();mContent.setText(note.getContent());mContent.setSelection(mContent.getText().toString().length());}}/*** 更新数据库的异步任务*/class UpdateAsyncTask extends AsyncTask<Void,Void,Void>{@Overrideprotected void onPreExecute() {super.onPreExecute();/*** 记录数据*/SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm");Date date = new Date(System.currentTimeMillis());noteTime = sdf.format(date);noteContent = mContent.getText().toString();note.setTime(noteTime);note.setContent(noteContent);}@Overrideprotected Void doInBackground(Void... voids) {mNoteDB.updateById(noteTime, noteContent, noteId);return null;}}/*** 根据是否有内容,提示保存*/private void updateDataOrNot() {if (!mContent.getText().toString().equals(originData)) {new AlertDialog.Builder(UpdateOrReadActivity.this).setTitle("提示").setMessage("需要保存您编辑的内容吗?").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {new UpdateAsyncTask().execute();finish();}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {finish();}}).show();} else {finish();}}/*** 返回键事件* 根据内容是否有变化,提示是否保存*/@Overridepublic void onBackPressed() {updateDataOrNot();}
}

操作数据库还是用了AsyncTask。这里,我考虑了,是否有改动,用一个变量,去存放原始的数据,在用户点击顶部返回或者系统返回键的时候去判断是否有改动,如果有,则提示用户是否需要保存更改。如果修改内容,没有字了,则自动删除该条记事本。因为删除记事本的操作,在主页还需要用到,所以我把它提出来,单独作为一个类,不再是内部类了。如下:

package com.ikok.notepad.Util;import android.os.AsyncTask;import com.ikok.notepad.DBUtil.NoteDB;/*** Created by Anonymous on 2016/3/25.*/
public class DeleteAsyncTask extends AsyncTask<Integer,Void,Void> {private NoteDB noteDB;public DeleteAsyncTask(NoteDB noteDB) {this.noteDB = noteDB;}@Overrideprotected Void doInBackground(Integer... params) {noteDB.deleteById(params[0]);return null;}}

接下来是CRUD的最后一项,删除数据了,在主页的时候,我设计的是单击进入该条记事本,去查看或修改这一条记事本,然后我考虑的是长按删除。长按,弹出对话框,提示是否删除,是则删除,否则不做任何事。所以在MainActivity中可以看到长按事件的监听器。但是因为Android的事件分发机制,长按事件必定会触发点击事件。所以需要在ListView中设置这样一个属性,才能点击事件和长按事件同时监听。

android:descendantFocusability="blocksDescendants"

主要功能都差不多完成了。接下来就是优化App了。我设计了过渡动画,引导页,以及是否第一次启动App。是则过渡动画过渡完到引导页,引导页完才到主页。否则过渡动画过渡完则直接进入主页。还设计了引导页的切换动画,使用了nineoldandroid,保证动画在低版本手机上可显示。

优化App部分可见我另外一篇博客,传送门: http://blog.csdn.net/someone_ikok/article/details/51027357

项目地址在:https://github.com/someonexiaole/Android

Notepad 即是。

欢迎大家 pr , star , fork , follow  我的 Github。

Android小项目:记事本相关推荐

  1. Android 小项目之--数据存储【Files】(附源码)

    继上篇数据存储,现在我们来讲讲另外一种数据存储,Files.本篇讲述步骤如下: 1.温故而知新,复习四种数据存储的区别. 2.什么是 Files 数据存储. 3.什么是 Properties ? 4. ...

  2. linux 蓝牙 手机遥控器,嵌入式Android小项目之万能手机遥控器详解

    原标题:嵌入式Android小项目之万能手机遥控器详解 在很久很久以前,手机是有红外功能的,后来随着蓝牙技术的成熟,红外逐渐被蓝牙取代,不再是标配了. 红外本身还是有些优点,比如操作简便,成本低.要想 ...

  3. Android小项目———— 冰炭不投de小计算器

    我的第一个Android小项目 冰炭不投de小计算器 一.前言 这是我首个使用java写的app,也在学习郭霖老师的第一行代码和李刚老师的疯狂java讲义之时,进行的练习之作,刚刚学习java和and ...

  4. Android小项目————聊天室(UI篇)

    Android小项目----聊天室(UI篇) 一.前言 这是所做的第二个android项目,主要目的对暑假所学的java和android知识点进行复习巩固和实践,由于知识所限,目前这个聊天室并不是很完 ...

  5. Android小项目——简易备忘录

    Android小项目--简易备忘录的实现 简易备忘录主要实现功能类似手机默认备忘录,可以对备忘录目录进行增添和删除.在编辑页面,可以显示当前时间,编辑备忘录标题,备忘录内容,设置时间提醒,插入图片等 ...

  6. 一个特别适合新手练习的Android小项目——每日一妹纸

    原文链接 http://sparkyuan.me/ 转载请注明出处 介绍 当前版本V 1.2 刚开始学习Android的时候,主要就是学习了一些Activity的生命周期,各种View和Layout的 ...

  7. Android小项目之--前台界面与用户交互的对接 进度条与拖动条(附源码)

    都知道水果公司(苹果)是己尊重用户体验著称的公司,其设计的产品人性化十足,不得不令后来者赞叹,竞相模仿.iphone的成功就是其典型的案例,做为其移动系统的死对头 Google 想要在市场上分得一杯羹 ...

  8. Android 小项目之--Mini音乐播放器【简单版】(附源码)

    上篇文章讲服务的例子中,有个演示服务的后台播放音乐,今天就来讲一讲多媒体之一的音乐播放. 说到多媒体不得不向上追溯,空间多媒体是如何实现的,如何可以让我们轻松的播放音乐.视频?本章讲述点大致如下: 1 ...

  9. Android小项目——新闻APP

    前言: 在公司学习了一段时间Android知识,决定做一个小项目,目的是学会运用所学的基础知识,在这里记录一下开发历程,大家可以把它看成一款入门级练手的 Demo 应用吧~ 项目概述: 类型: 新闻A ...

  10. android小项目之新闻客户端四

     基于Android小巫新闻客户端开发---显示新闻详细内容UI设计 2013年2月27日,天气潮湿!!! 距上一次写的主界面业务逻辑实现,已经过来11天,小巫觉得拖得太久了,所以决定尽量把所有的 ...

最新文章

  1. C# T 泛型类,泛型方法的约束条件用法
  2. H5 的getImageData造成的大量内存开销
  3. 图Graph--拓扑排序(Topological Sorting)
  4. c++ httpserver 服务器
  5. 100g光模块厂家排名_100G光模块固件设计示例
  6. raid5加热备盘_联想服务器X3650 M2 配置RAID5与热备盘图文方法
  7. 华为鸿蒙系统备用,就只有华为有备用系统?其实谷歌也准备了一个,不输鸿蒙系统!...
  8. SpringBoot整合Jersey2.x实现文件上传API
  9. 58、IPv6访问控制列表及ICMPv6简介
  10. 编程常用单词1500个
  11. 结构化思维的理解与思考
  12. librosa audioread.NoBackendError
  13. MySQL8.0.11修改root密码
  14. Spring自动装配及自动注入
  15. :first-child和:first-of-type的区别
  16. 2021-11-21 根据身高 体重计算出bmi指数,检测自己是否属于肥胖
  17. 【Gaze】Generating Image Descriptions via Sequential Cross-Modal Alignment Guided by Human Gaze
  18. 上海三菱电梯LEHY,LEGY,上海三菱,758 .778详 细地址码,总共100多页
  19. c语言实现傅里叶变换
  20. 微云存照片会变模糊吗_把照片存QQ相册会越来越模糊,你们会把照片存在哪里?...

热门文章

  1. idea禁用Run Anything
  2. 军事仿真新纪元——全数据实时驱动视景仿真
  3. 【Postman】 测试文件上传、下载
  4. 企业数据仓库架构(医药)
  5. 区块链电子签名技术及方案
  6. Skin Snap Art 4破解版下载
  7. Pygame详解(十二):Surface 对象
  8. 扫描机扫描文件之后服务器出错,扫描仪使用过程中常见问题解决方法总结
  9. Windows网络基础
  10. 《算法笔记》学习笔记——2.3选择结构