本文基于Java实现了一个简单的记事本安卓app,用的是SQLite数据库,包括布局文件、源码及实现图。
布局设计
记事本主界面
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http:///apk/res/android"
xmlns:app="http:///apk/res-auto"
xmlns:tools="http:///tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".NoteActivity">
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="8dp"
android:layout_below="@+id/myToolbar"
android:divider="?attr/lvBackground"
android:dividerHeight="8dp"
>
</ListView>
<androidx.appcompat.widget.Toolbar
android:id="@+id/myToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:titleTextColor="?attr/titleColor"
android:theme="?attr/toolbarTheme"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
</androidx.appcompat.widget.Toolbar>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginEnd="36dp"
android:layout_marginBottom="48dp"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_add_white_24dp"
/>
</RelativeLayout>
对记事本编辑的页面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http:///apk/res/android"
xmlns:app="http:///apk/res-auto"
xmlns:tools="http:///tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".EditNoteActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/my_Toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:titleTextColor="?attr/titleColor"
android:theme="?attr/toolbarTheme"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
</androidx.appcompat.widget.Toolbar>
<EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="200dp"
android:inputType="text"
android:gravity="top">
</EditText>
</LinearLayout>
代码
Note实体类
记事信息实体类
public class Note {
private long id;
private String content;
private String time;
private int tag;
public Note() {
}
public Note(String content, String time, int tag) {
this.content = content;
this.time = time;
this.tag = tag;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
public String getTime() {
return time;
}
public int getTag() {
return tag;
}
public void setId(long id) {
this.id = id;
}
public void setContent(String content) {
this.content = content;
}
public void setTime(String time) {
this.time = time;
}
public void setTag(int tag) {
this.tag = tag;
}
@Override
public String toString() {
return content + "\n" + time.substring(5, 16) + " " + id;
}
}
NoteActivity
记事本主界面的Activity
import androidx.annotation.Nullable;
import .AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList;
import java.util.List;
public class NoteActivity extends BaseActivity implements AdapterView.OnItemClickListener {
FloatingActionButton btn;
private ListView lv;
private NoteAdapter adapter;
private List<Note> noteList = new ArrayList<Note>();
private Context context = this;
private Toolbar myToolbar;
final String TAG = "tag";
private NoteDatabase dbHelper;
private Menu menu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note);
btn = (FloatingActionButton) findViewById(.fab);
lv = (ListView) findViewById();
myToolbar = findViewById(.myToolbar);
adapter = new NoteAdapter(getApplicationContext(), noteList);
refreshListView();
lv.setAdapter(adapter);
setSupportActionBar(myToolbar);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); //设置toolbar取代actionbar
lv.setOnItemClickListener(this);
myToolbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp);
myToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(NoteActivity.this, SliderActivity.class));
}
});
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(NoteActivity.this, EditNoteActivity.class);
intent.putExtra("mode", 4);
startActivityForResult(intent, 0);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
int returnMode;
long note_Id;
returnMode = data.getExtras().getInt("mode", -1);
note_Id = data.getExtras().getLong("id", 0);
if (returnMode == 1) { //update current note
String content = data.getExtras().getString("content");
String time = data.getExtras().getString("time");
int tag = data.getExtras().getInt("tag", 1);
Note newNote = new Note(content, time, tag);
newNote.setId(note_Id);
CRUD op = new CRUD(context);
op.open();
op.updateNote(newNote);
op.close();
} else if (returnMode == 0) { // create new note
String content = data.getExtras().getString("content");
String time = data.getExtras().getString("time");
int tag = data.getExtras().getInt("tag", 1);
Note newNote = new Note(content, time, tag);
CRUD op = new CRUD(context);
op.open();
op.addNote(newNote);
op.close();
} else if (returnMode == 2) { // delete
Note curNote = new Note();
curNote.setId(note_Id);
CRUD op = new CRUD(context);
op.open();
op.removeNote(curNote);
op.close();
} else {
}
refreshListView();
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
//search setting
MenuItem mSearch = menu.findItem(.action_search);
SearchView mSearchView = (SearchView) mSearch.getActionView();
mSearchView.setQueryHint("Search");
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
public void refreshListView() {
CRUD op = new CRUD(context);
op.open();
// set adapter
if (noteList.size() > 0) noteList.clear();
noteList.addAll(op.getAllNotes());
op.close();
adapter.notifyDataSetChanged();
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
switch (parent.getId()) {
case :
Note curNote = (Note) parent.getItemAtPosition(position);
Intent intent = new Intent(NoteActivity.this, EditNoteActivity.class);
intent.putExtra("content", curNote.getContent());
intent.putExtra("id", curNote.getId());
intent.putExtra("time", curNote.getTime());
intent.putExtra("mode", 3); // MODE of 'click to edit'
intent.putExtra("tag", curNote.getTag());
startActivityForResult(intent, 1); //collect data from edit
Log.d(TAG, "onItemClick: " + position);
break;
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case .menu_clear:
new AlertDialog.Builder(NoteActivity.this)
.setMessage("删除全部吗?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dbHelper = new NoteDatabase(context);
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("notes", null, null);
db.execSQL("update sqlite_sequence set seq=0 where name='notes'");
refreshListView();
}
}).setNegativeButton(, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).create().show();
break;
}
return super.onOptionsItemSelected(item);
}
}
NoteAdapter
适配器为主界面列表绑定数据
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class NoteAdapter extends BaseAdapter implements Filterable {
private Context mContext;
private List<Note> backList;//用来备份原始数据
private List<Note> noteList;//这个数据是会改变的,所以要有个变量来备份一下原始数据
private MyFilter mFilter;
public NoteAdapter(Context mContext, List<Note> noteList) {
this.mContext = mContext;
this.noteList = noteList;
backList = noteList;
}
@Override
public int getCount() {
return noteList.size();
}
@Override
public Object getItem(int position) {
return noteList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
mContext.setTheme(R.style.DayTheme);
View v = View.inflate(mContext, R.layout.note_layout, null);
TextView tv_content = (TextView) v.findViewById(.tv_content);
TextView tv_time = (TextView) v.findViewById(.tv_time);
//Set text for TextView
String allText = noteList.get(position).getContent();
/*if (sharedPreferences.getBoolean("noteTitle" ,true))
tv_content.setText(allText.split("\n")[0]);*/
tv_content.setText(allText);
tv_time.setText(noteList.get(position).getTime());
//Save note id to tag
v.setTag(noteList.get(position).getId());
return v;
}
@Override
public Filter getFilter() {
if (mFilter == null) {
mFilter = new MyFilter();
}
return mFilter;
}
class MyFilter extends Filter {
//在performFiltering(CharSequence charSequence)这个方法中定义过滤规则
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults result = new FilterResults();
List<Note> list;
if (TextUtils.isEmpty(charSequence)) {//当过滤的关键字为空的时候,我们则显示所有的数据
list = backList;
} else {//否则把符合条件的数据对象添加到集合中
list = new ArrayList<>();
for (Note note : backList) {
if (note.getContent().contains(charSequence)) {
list.add(note);
}
}
}
result.values = list; //将得到的集合保存到FilterResults的value变量中
result.count = list.size();//将集合的大小保存到FilterResults的count变量中
return result;
}
//在publishResults方法中告诉适配器更新界面
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
noteList = (List<Note>) filterResults.values;
if (filterResults.count > 0) {
notifyDataSetChanged();//通知数据发生了改变
} else {
notifyDataSetInvalidated();//通知数据失效
}
}
}
}
NoteDatabase
用到的是SQLite数据库,Android自带了一种轻量级数据库,使用非常方便。
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class NoteDatabase extends SQLiteOpenHelper {
public static final String TABLE_NAME = "notes";
public static final String CONTENT = "content";
public static final String ID = "_id";
public static final String TIME = "time";
public static final String MODE = "mode";
public NoteDatabase(Context context) {
super(context, "notes", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME
+ "("
+ ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ CONTENT + " TEXT NOT NULL,"
+ TIME + " TEXT NOT NULL,"
+ MODE + " INTEGER DEFAULT 1)"
);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
EditNoteActivity
编辑页面的Activity
import .AlertDialog;
import androidx.appcompat.widget.Toolbar;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.KeyEvent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import java.text.SimpleDateFormat;
import java.util.Date;
public class EditNoteActivity extends BaseActivity {
private EditText et;
private Toolbar myToolbar;
private String old_content = "";
private String old_time = "";
private int old_Tag = 1;
private long id = 0;
private int openMode = 0;
private int tag = 1;
public Intent intent = new Intent(); // message to be sent
private boolean tagChange = false;
private final String TAG = "tag";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_note);
myToolbar = findViewById(.my_Toolbar);
setSupportActionBar(myToolbar);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); //设置toolbar取代actionbar
myToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
autoSetMessage();
setResult(RESULT_OK, intent);
finish();
}
});
et = findViewById(.et);
Intent getIntent = getIntent();
openMode = getIntent.getIntExtra("mode", 0);
if (openMode == 3) {//打开已存在的note
id = getIntent.getLongExtra("id", 0);
old_content = getIntent.getStringExtra("content");
old_time = getIntent.getStringExtra("time");
old_Tag = getIntent.getIntExtra("tag", 1);
et.setText(old_content);
et.setSelection(old_content.length());
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_HOME) {
return true;
} else if (keyCode == KeyEvent.KEYCODE_BACK) {
autoSetMessage();
setResult(RESULT_OK, intent);
finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
public String dateToStr() {
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.format(date);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case .delete:
new AlertDialog.Builder(EditNoteActivity.this)
.setMessage("删除吗?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (openMode == 4) { // new note
intent.putExtra("mode", -1);
setResult(RESULT_OK, intent);
} else { // existing note
intent.putExtra("mode", 2);
intent.putExtra("id", id);
setResult(RESULT_OK, intent);
}
finish();
}
}).setNegativeButton(, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).create().show();
break;
}
return super.onOptionsItemSelected(item);
}
public void autoSetMessage() {
if (openMode == 4) {
if (et.getText().toString().length() == 0) {
intent.putExtra("mode", -1); //nothing new happens.
} else {
intent.putExtra("mode", 0); // new one note;
intent.putExtra("content", et.getText().toString());
intent.putExtra("time", dateToStr());
intent.putExtra("tag", tag);
}
} else {
if (et.getText().toString().equals(old_content) && !tagChange)
intent.putExtra("mode", -1); // edit nothing
else {
intent.putExtra("mode", 1); //edit the content
intent.putExtra("content", et.getText().toString());
intent.putExtra("time", dateToStr());
intent.putExtra("id", id);
intent.putExtra("tag", tag);
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.edit_menu, menu);
return super.onCreateOptionsMenu(menu);
}
}
CRUD
对SQLite数据库增删改查操作,增加、删除、修改、查询记事信息
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
public class CRUD {
SQLiteOpenHelper dbHandler;
SQLiteDatabase db;
private static final String[] columns = {
NoteDatabase.ID,
NoteDatabase.CONTENT,
NoteDatabase.TIME,
NoteDatabase.MODE
};
public CRUD(Context context){
dbHandler = new NoteDatabase(context);
}
public void open(){
db = dbHandler.getWritableDatabase();
}
public void close(){
dbHandler.close();
}
//把note 加入到database里面
public Note addNote(Note note){
//add a note object to database
ContentValues contentValues = new ContentValues();
contentValues.put(NoteDatabase.CONTENT, note.getContent());
contentValues.put(NoteDatabase.TIME, note.getTime());
contentValues.put(NoteDatabase.MODE, note.getTag());
long insertId = db.insert(NoteDatabase.TABLE_NAME, null, contentValues);
note.setId(insertId);
return note;
}
public Note getNote(long id){
//get a note from database using cursor index
Cursor cursor = db.query(NoteDatabase.TABLE_NAME,columns,NoteDatabase.ID + "=?",
new String[]{String.valueOf(id)},null,null, null, null);
if (cursor != null) cursor.moveToFirst();
Note e = new Note(cursor.getString(1),cursor.getString(2), cursor.getInt(3));
return e;
}
public List<Note> getAllNotes(){
Cursor cursor = db.query(NoteDatabase.TABLE_NAME,columns,null,null,null, null, null);
List<Note> notes = new ArrayList<>();
if(cursor.getCount() > 0){
while(cursor.moveToNext()){
Note note = new Note();
note.setId(cursor.getLong(cursor.getColumnIndex(NoteDatabase.ID)));
note.setContent(cursor.getString(cursor.getColumnIndex(NoteDatabase.CONTENT)));
note.setTime(cursor.getString(cursor.getColumnIndex(NoteDatabase.TIME)));
note.setTag(cursor.getInt(cursor.getColumnIndex(NoteDatabase.MODE)));
notes.add(note);
}
}
return notes;
}
public int updateNote(Note note) {
//update the info of an existing note
ContentValues values = new ContentValues();
values.put(NoteDatabase.CONTENT, note.getContent());
values.put(NoteDatabase.TIME, note.getTime());
values.put(NoteDatabase.MODE, note.getTag());
// updating row
return db.update(NoteDatabase.TABLE_NAME, values,
NoteDatabase.ID + "=?",new String[] { String.valueOf(note.getId())});
}
public void removeNote(Note note) {
//remove a note according to ID value
db.delete(NoteDatabase.TABLE_NAME, NoteDatabase.ID + "=" + note.getId(), null);
}
}
结果