Android-备忘录开发

1 前言

由于项目需求,最近需要开发一个备忘录,备忘录对于Android是一个很普遍的功能。其实我内心os是每台手机自带的系统就有备忘录功能,在一个App中再开发一个备忘录功能实在是鸡肋。然鹅,做项目就是这样,老板喊做,那我就做着呗。由于为了毕业还要看文献看算法什么的,平时也没什么时间,所以这次只是简单的做了一个可以基于SQLite本地数据库进行备忘录增删查改操作的一个功能。主要实现以下几点功能:

  • 备忘录的增删查改功能
  • 每条备忘录包含标题、内容、时间
  • 备忘录的排列顺序按照时间来,后来居上

2 预备知识

2.1 SQLite基础

在很多项目开发中,我们或多或少都会用到数据库。在Android中,我们一般使用SQLite。因为Android在android.database.sqlite包封装了很多SQLite的API。

继承SQLiteOpenHelper

在使用SQLite时,首先创建一个继承SQLiteOpenHelper的类,并重写onCreate()onUpgrade()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class OrderDBHelper extends SQLiteOpenHelper{
private static final int DB_VERSION = 1;
private static final String DB_NAME = "myTest.db";
public static final String TABLE_NAME = "Orders";
public OrderDBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// create table Orders(Id integer primary key, CustomName text, OrderPrice integer, Country text);
String sql = "create table if not exists " + TABLE_NAME + " (Id integer primary key, CustomName text, OrderPrice integer, Country text)";
sqLiteDatabase.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
String sql = "DROP TABLE IF EXISTS " + TABLE_NAME;
sqLiteDatabase.execSQL(sql);
onCreate(sqLiteDatabase);
}
}

这个类的作用主要是用来创建数据库和建表用,一般来说,我们会再创建一个OrderDao类用于处理所有的数据操作方法。在OrderDao中实例化OrderDBHelper:

1
2
3
4
public OrderDao(Context context) {
this.context = context;
ordersDBHelper = new OrderDBHelper(context);
}

SQLite的增删查改操作

数据库操作无外乎“增删查改”,我们依据操作是否对数据库有改动将其分为两类:

  • “增删改”
    对于“增删改”这类对表内容变换的操作,我们需要先调用getWritableDatabase(),执行的时候可以调用通用的excecSQL(String sql)方法或对应的操作API:insert()delete()update()

  • “查”
    对于“查”这种对表内容无影响的操作,我们需要调用getReadableDatabase(),这时就不能用execSQL方法,而该改用query()rawQuery()方法。

增加数据
  • 数据量较多时
    开启事物进行添加:
1
2
3
4
5
6
7
8
9
10
11
db = ordersDBHelper.getWritableDatabase();
db.beginTransaction();
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (1, 'Arc', 100, 'China')");
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (2, 'Bor', 200, 'USA')");
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (3, 'Cut', 500, 'Japan')");
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (4, 'Bor', 300, 'USA')");
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (5, 'Arc', 600, 'China')");
db.execSQL("insert into " + OrderDBHelper.TABLE_NAME + " (Id, CustomName, OrderPrice, Country) values (6, 'Doom', 200, 'China')");
db.setTransactionSuccessful();
  • 插入一条新数据
    可以使用insert(String table, String nullColumnHack, ContentValues values)方法来插入,ContentValues内部实现就是HashMap,但是两者还是有区别的,ContentValues的Key只能存储String类型,Value只能存储基本数据类型以及String类型这些,不能存储对象。
1
2
3
4
5
6
7
8
9
10
11
12
db = ordersDBHelper.getWritableDatabase();
db.beginTransaction();
// insert into Orders(Id, CustomName, OrderPrice, Country) values (7, "Jne", 700, "China");
ContentValues contentValues = new ContentValues();
contentValues.put("Id", 7);
contentValues.put("CustomName", "Jne");
contentValues.put("OrderPrice", 700);
contentValues.put("Country", "China");
db.insertOrThrow(OrderDBHelper.TABLE_NAME, null, contentValues);
db.setTransactionSuccessful();
删除数据

delete(String table, String WhereClause, String[] WhereArgs),whereClause是删除条件,whereArgs是删除条件值数组

1
2
3
4
5
6
db = ordersDBHelper.getWritableDatabase();
db.beginTransaction();
// delete from Orders where Id = 7
db.delete(OrderDBHelper.TABLE_NAME, "Id = ?", new String[]{String.valueOf(7)});
db.setTransactionSuccessful();
修改数据

update(String table, ContentValues, String whereClause, String[] whereArgs)

1
2
3
4
5
6
7
8
9
10
11
db = ordersDBHelper.getWritableDatabase();
db.beginTransaction();
// update Orders set OrderPrice = 800 where Id = 6
ContentValues cv = new ContentValues();
cv.put("OrderPrice", 800);
db.update(OrderDBHelper.TABLE_NAME,
cv,
"Id = ?",
new String[]{String.valueOf(6)});
db.setTransactionSuccessful();
查找数据
  • public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy,String limit)
    query中的参数如下:
参数 含义
table 表名
columns 列名称数组
selection 条件字句,相当于where
selectionArgs 条件字句,参数数组
groupBy 分组列
having 分组条件
orderBy 排序列
orderBy 排序列
limit 分页查询限制
cursor 返回值

返回值类型是CursorCursor是一个游标接口,提供了遍历查询结果的方法,如移动指针方法move(),获得列值。Cursor游标常用方法如下:

enter image description here

  • public Cursor rawQuery(String sql, String[] selectionArgs)

类似execSQL方法,不做介绍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
db = ordersDBHelper.getReadableDatabase();
// select * from Orders where CustomName = 'Bor'
cursor = db.query(OrderDBHelper.TABLE_NAME,
ORDER_COLUMNS,
"CustomName = ?",
new String[] {"Bor"},
null, null, null);
if (cursor.getCount() > 0) {
List<Order> orderList = new ArrayList<Order>(cursor.getCount());
while (cursor.moveToNext()) {
Order order = parseOrder(cursor);
orderList.add(order);
}
return orderList;
}

2.2 FloatingActionButton的使用

Floating Action Button(FAB)是众多专家大牛针对Material Design讨论比较细化的一个点,通过圆形元素与分割线、卡片、各种Bar的直线形成鲜明对比,并使用色彩设定中鲜艳的辅色,带来更具突破性的视觉效果。也正因此,在github上,有着许多与FAB相关的开源项目,其具有弹出特效与自动隐藏等功能,虽然本次并没有用到。简单介绍 如何使用:

2.2.1 导入依赖

1
2
3
dependencies {
compile 'com.getbase:floatingactionbutton:1.10.1'
}

2.2.2 添加View到layout的xml文件中

  • 声明自定义命名空间
1
xmlns:fab="http://schemas.android.com/apk/res-auto"
  • 添加com.getbase.floatingactionbutton.FloatingActionButton
1
2
3
4
5
6
7
8
9
10
11
<com.getbase.floatingactionbutton.FloatingActionButton
android:id="@+id/add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_margin="15dp"
android:src="@drawable/ic_add"
fab:fab_colorNormal="#37c674"
fab:fab_colorPressed="@color/white" />

2.2.3 实现弹出菜单功能

这次我并没有做弹出菜单功能,只是给button绑定了一个监听器进行activity之间的跳转。如果有需要用到其弹窗功能,可以参考以下链接:FloatingActionButton的使用

2.3 CardView的使用

CardView继承自FrameLayout类,是一种卡片视图,以卡片形式显示内容。卡片布局可以设置圆角与阴影,还可以布局其他的View。CardView可以作为一般的布局使用,也可以作为ListView和RecyclerView的Item使用。

2.3.1 导入依赖

CardView的位置在supportV7包之中,因此,在使用时,需要导入v7包的依赖。

1
compile 'com.android.support:cardview-v7:24.0.0'

2.3.2 CardView属性

  • android:cardCornerRadius:设置card圆角的大小
  • android:cardBackgroundColor:设置card的背景颜色
  • android:elevation:设置阴影的大小
  • android:contentPadding:设置卡片内容与边界的间隔
  • android:cardUseCompatPadding:设置内边距,防止内容与边角的重叠

2.3.3 CardView作为listView中单个item的布局

用来显示单条备忘录内容的布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="6dp"
card_view:cardElevation="4dp"
card_view:cardUseCompatPadding="true"
card_view:contentPadding="10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/note_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginBottom="8dp"
android:textColor="#ff000000"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/note_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/note_title"
android:layout_marginBottom="8dp"
android:textColor="#ff000000" />
<TextView
android:id="@+id/note_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/note_content"
android:textColor="#ff2a0f5c"
android:textSize="12sp"
android:textStyle="italic" />
<TextView
android:id="@+id/note_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>

3 备忘录实战

3.1 数据库相关类封装

3.1.1 NoteOpenHelper继承自SQLiteOpenHelper

用于创建数据库及备忘录表,每条记录有4个字段,分别是id(主键,自增)、content(备忘录内容)、title(备忘录标题)、time(备忘录记录时间),其代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class NoteOpenHelper extends SQLiteOpenHelper {
public static final String TABLE_NAME = "note";
public static final int VERSION = 1;
public static final String TITLE = "title";
public static final String CONTENT = "content";
public static final String TIME = "time";
public static final String ID = "_id";
public NoteOpenHelper(Context context) {
super(context, TABLE_NAME, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("create table if not exists " + TABLE_NAME + " ("
+ ID + " integer primary key autoincrement,"
+ CONTENT + " text not null,"
+ TITLE + " text not null,"
+ TIME + " text not null)");
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
```

3.1.2 数据库操作类DBManager

SQLite的数据库的增删查改若不经过一番封装,代码将显得冗余不优雅,因此将其封装在一个操作类中,代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
public class DBManger {
private Context context;
private NoteOpenHelper databaseOpenHelper;
private SQLiteDatabase dbReader;
private SQLiteDatabase dbWriter;
private static DBManger instance;
public DBManger(Context context){
this.context = context;
databaseOpenHelper = new NoteOpenHelper(context);
//创建、打开一个数据库
dbReader = databaseOpenHelper.getReadableDatabase();
dbWriter = databaseOpenHelper.getWritableDatabase();
}
/**
* getInstance单例
* @param context
* @return
*/
public static synchronized DBManger getInstance(Context context){
if(instance == null){
instance = new DBManger(context);
}
return instance;
}
/**
* 添加纪录至数据库
* @param title
* @param content
* @param time
*/
public void addToDB(String title, String content, String time){
//组装数据
ContentValues cv = new ContentValues();
cv.put(NoteOpenHelper.TITLE, title);
cv.put(NoteOpenHelper.CONTENT, content);
cv.put(NoteOpenHelper.TIME, time);
dbWriter.insert(NoteOpenHelper.TABLE_NAME, null, cv);
}
/**
* 读取数据
* @param noteList
*/
public void readFromDB(List<Note> noteList){
Cursor cursor = dbReader.query(NoteOpenHelper.TABLE_NAME, null, null, null, null, null, null);
try{
while(cursor.moveToNext()){
Note note = new Note();
note.setId(cursor.getInt(cursor.getColumnIndex(NoteOpenHelper.ID)));
note.setTitle(cursor.getString(cursor.getColumnIndex(NoteOpenHelper.TITLE)));
note.setContent(cursor.getString(cursor.getColumnIndex(NoteOpenHelper.CONTENT)));
note.setTime(cursor.getString(cursor.getColumnIndex(NoteOpenHelper.TIME)));
noteList.add(note);
}
cursor.close();
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 更新数据
* @param noteID
* @param title
* @param content
* @param time
*/
public void updateNote(int noteID, String title, String content, String time) {
ContentValues cv = new ContentValues();
cv.put(NoteOpenHelper.ID, noteID);
cv.put(NoteOpenHelper.TITLE, title);
cv.put(NoteOpenHelper.CONTENT, content);
cv.put(NoteOpenHelper.TIME, time);
dbWriter.update(NoteOpenHelper.TABLE_NAME, cv, "_id = ?", new String[]{noteID + ""});
}
/**
* 删除数据
* @param noteID
*/
public void deleteNote(int noteID) {
dbWriter.delete(NoteOpenHelper.TABLE_NAME, "_id = ?", new String[]{noteID + ""});
}
/**
* 根据ID查询数据
* @param noteID
* @return
*/
public Note readData(int noteID) {
Cursor cursor = dbReader.rawQuery("SELECT * FROM note WHERE _id = ?", new String[]{noteID + ""});
Note note = new Note();
System.out.println("database:cursor:" + cursor);
if(cursor != null && cursor.moveToFirst()){
note.setId(cursor.getInt(cursor.getColumnIndex(NoteOpenHelper.ID)));
note.setTitle(cursor.getString(cursor.getColumnIndex(NoteOpenHelper.TITLE)));
note.setContent(cursor.getString(cursor.getColumnIndex(NoteOpenHelper.CONTENT)));
}
return note;
}
}

3.2 备忘录列表listView适配器

这个就没什么好说的了,为了提高性能,用了ViewHolder。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public class MyAdapter extends BaseAdapter {
private Context context;
private List<Note> notes;
public MyAdapter(Context context, List<Note> notes) {
this.context = context;
//实现倒序排列
Collections.reverse(notes);
this.notes = notes;
}
public void removeAllItem() {
notes.clear();
notifyDataSetChanged();
}
public void removeItem(int position) {
notes.remove(position);
notifyDataSetChanged();
}
@Override
public int getCount() {
return notes.size();
}
@Override
public Note getItem(int i) {
return notes.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int position, View convertView, final ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.item_note, null);
viewHolder = new ViewHolder();
viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.note_title);
viewHolder.tvContent = (TextView) convertView.findViewById(R.id.note_content);
viewHolder.tvTime = (TextView) convertView.findViewById(R.id.note_time);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.setId(notes.get(position).getId());
viewHolder.tvTitle.setText(notes.get(position).getTitle());
viewHolder.tvContent.setText(notes.get(position).getContent());
viewHolder.tvTime.setText(notes.get(position).getTime());
convertView.setTag(viewHolder);
return convertView;
}
public static class ViewHolder {
public int Id;
public TextView tvTitle;
public TextView tvContent;
public TextView tvTime;
public void setId(int id) {
Id = id;
}
}
}

3.3 主界面和编辑界面

3.3.1 主界面

主界面布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fab="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:layout_width="fill_parent"
android:layout_height="@dimen/head_h"
layout="@layout/inc_head" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@null"></ListView>
<TextView
android:id="@+id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:gravity="center"
android:text="点击右下方图标添加备忘"
android:textSize="16sp" />
<com.getbase.floatingactionbutton.FloatingActionButton
android:id="@+id/add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_margin="15dp"
android:src="@drawable/ic_add"
fab:fab_colorNormal="#37c674"
fab:fab_colorPressed="@color/white" />
</RelativeLayout>
</LinearLayout>

主要是一个Listview和FAB,以及一个TextView,用以在当没有备忘录条目时,默认提示“点击右下方按钮增加备忘”。

Activity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
public class ChiefNotepadActivity extends BaseActivity {
private FloatingActionButton addBtn;
private TextView emptyListTextView;
private DBManger dm;
private List<Note> noteDataList = new ArrayList<>();
private MyAdapter adapter;
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chief_notepad);
setTitle("备忘录");
initHead(R.drawable.ic_head_back, 0);
initNotePad();
}
private void initNotePad() {
dm = new DBManger(this);
dm.readFromDB(noteDataList);
listView = (ListView) findViewById(R.id.list);
addBtn = (FloatingActionButton) findViewById(R.id.add);
emptyListTextView = (TextView) findViewById(R.id.empty);
addBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent i = new Intent(ChiefNotepadActivity.this, ChiefEditNoteActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
});
// adapter = new MyAdapter(this, noteDataList);
adapter = new MyAdapter(this, noteDataList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new NoteClickListener());
listView.setOnItemLongClickListener(new NoteLongClickListener());
updateView();
}
//listView单击事件
private class NoteClickListener implements AdapterView.OnItemClickListener{
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
MyAdapter.ViewHolder viewHolder = (MyAdapter.ViewHolder) view.getTag();
int noteId = viewHolder.Id;
Intent intent = new Intent(ChiefNotepadActivity.this, ChiefEditNoteActivity.class);
intent.putExtra("id", noteId);
startActivity(intent);
}
}
//listView长按事件
private class NoteLongClickListener implements AdapterView.OnItemLongClickListener {
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, final int i, long l) {
final Note note = ((MyAdapter) adapterView.getAdapter()).getItem(i);
if (note == null) {
return true;
}
final int id = note.getId();
new MaterialDialog.Builder(ChiefNotepadActivity.this)
.content("确定删除此条笔记?")
.positiveText("确定")
.negativeText("取消")
.callback(new MaterialDialog.ButtonCallback(){
@Override
public void onPositive(MaterialDialog dialog) {
DBManger.getInstance(ChiefNotepadActivity.this).deleteNote(id);
adapter.removeItem(i);
updateView();
}
}).show();
return true;
}
}
//数据更新
private void updateView() {
if (noteDataList.isEmpty()) {
listView.setVisibility(View.GONE);
emptyListTextView.setVisibility(View.VISIBLE);
} else {
listView.setVisibility(View.VISIBLE);
emptyListTextView.setVisibility(View.GONE);
}
}
}

主要是初始化和三个监听事件函数:

  • 点击addBtn时,跳转至编辑界面
  • 短按listView中的条目时,跳转至编辑界面,修改备忘录内容界面
  • 长按listView中的条目时,弹窗,提示是否删除该条备忘录

其中在跳转界面时,给Intent设置标志FLAG_ACTIVITY_CLEAR_TOP的原因在于,怕用户在主界面与编辑界面之间反复跳转时,会在栈中存留多个activity界面,而影响用户体验。

3.3.2 编辑界面

界面布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fab="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:layout_width="fill_parent"
android:layout_height="@dimen/head_h"
layout="@layout/inc_head" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<EditText
android:id="@+id/note_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入备忘标题"
android:maxLength="50"
android:textSize="@dimen/news_item_title_textsize"
android:maxLines="1">
<requestFocus />
</EditText>
<EditText
android:id="@+id/note_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/note_title"
android:gravity="start"
android:hint="请在此输入备忘内容"
android:inputType="textMultiLine" />
<ImageView
android:id="@+id/note_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/save" />
<com.getbase.floatingactionbutton.FloatingActionButton
android:id="@+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_margin="15dp"
android:src="@drawable/ic_action_save"
fab:fab_colorNormal="#37c674"
fab:fab_colorPressed="@color/white" />
</RelativeLayout>
</LinearLayout>

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package com.zju.hzsz.chief.activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Selection;
import android.text.Spannable;
import android.view.View;
import android.widget.EditText;
import com.getbase.floatingactionbutton.FloatingActionButton;
import com.zju.hzsz.R;
import com.zju.hzsz.db.DBManger;
import com.zju.hzsz.model.Note;
import java.util.Date;
/**
* Created by Wangli on 2017/3/8.
*/
public class ChiefEditNoteActivity extends BaseActivity {
private EditText titleEt;
private EditText contentEt;
private FloatingActionButton saveBtn;
private int noteID = -1;
private DBManger dbManger;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chief_editnote);
setTitle("编辑备忘");
initHead(R.drawable.ic_head_back, 0);
initEditNotePad();
}
private void initEditNotePad() {
dbManger = new DBManger(this);
titleEt = (EditText) findViewById(R.id.note_title);
contentEt = (EditText) findViewById(R.id.note_content);
saveBtn = (FloatingActionButton) findViewById(R.id.save);
saveBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String title = titleEt.getText().toString();
String content = contentEt.getText().toString();
String time = getTime();
//将最新修改的放最前面
if ( noteID != -1) {
dbManger.deleteNote(noteID);
}
dbManger.addToDB(title, content, time);
Intent i = new Intent(ChiefEditNoteActivity.this, ChiefNotepadActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
}
});
noteID = getIntent().getIntExtra("id", -1);
if (noteID != -1) {
showNoteData(noteID);
}
}
private void showNoteData(int noteID) {
Note note = dbManger.readData(noteID);
titleEt.setText(note.getTitle());
contentEt.setText(note.getContent());
//控制光标
Spannable spannable = titleEt.getText();
Selection.setSelection(spannable, titleEt.getText().length());
}
private String getTime() {
java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("MM-dd HH:mm E");
Date curDate = new Date();
String str = format.format(curDate);
return str;
}
}

以及Note类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Note {
public int noteId;
public String title;
public String content;
public String time;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getId() {
return noteId;
}
public void setId(int id) {
this.noteId = id;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

值得一说的是,将listView倒序排列。用到的语句是:

1
Collections.reverse(List< ? >);

以及重新编辑一条备忘之后,要将这条备忘的原记录删除,再将新编辑后的备忘置顶。

整个开发流程,大致就是这样。

上两张图吧:

@备忘录主界面

@备忘录编辑界面

Compartir Comentarios