Android实现记事本
记事本 Android实现
一、效果展示
二、总体框架
1、框架图
2、SQLite数据库
三、实现步骤
1、activity_main.xml布局文件
<?xml version="1.0" encoding="utf-8"?>
2、新建列表子项布局文件item.xml
<?xml version="1.0" encoding="utf-8"?>
3、修改清单文件的theme 属性,去掉默认标题栏。
android:theme="@style/Theme.AppCompat.NoActionBar">
4、新建 Bean .java文件,定义备忘录信息的所有属性,封装备忘录信息实体类,与数据库表中信息对应。
package com.example.mynote;
public class Bean
{
private String id; //记录的 id
private String bthings; //记录的内容
private String btime; //保存记录的时间
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public String getNotepadContent()
{
return bthings;
}
public void setNotepadContent(String notepadContent)
{
this.bthings = notepadContent;
}
public String getNotepadTime()
{
return btime;
}
public void setNotepadTime(String notepadTime)
{
this.btime = notepadTime;
}
}
5、新建数据适配器 NoteAdapter 对 ListView 控件进行数据适配
//创建 NoteAdapter 类,继承自 BaseAdapter 类。
public class NoteAdapter extends BaseAdapter
{
private List list; //数据准备
private Context mycontext;
private LayoutInflater myinflate; //加载布局视图
//构造函数
public NoteAdapter(Context context,List list)
{
this.list=list;
this.mycontext=context;
this.myinflate=LayoutInflater.from(context);
}
//实现4个方法
@Override
public int getCount()
{ //返回列表长度
return list.size();
}
@Override
public Object getItem(int position)
{ //返回控件
return list.get(position);
}
@Override
public long getItemId(int i)
{ //返回下标
return i;
}
@Override
//参数convertview用于复用列表项布局View,vgroup用于加载列表项xml布局
public View getView(int i, View convertview, ViewGroup vgroup)
{
ViewHolder myholder;
//如果没有空闲的列表项就新创建一个
if(convertview==null)
{
convertview=myinflate.inflate(R.layout.item,null);
myholder=new ViewHolder(convertview);
convertview.setTag(myholder);
}
else
{
myholder=(ViewHolder) convertview.getTag();
}
final Bean info=(Bean) getItem(i);
myholder.textView_things.setText(info.getNotepadContent());
myholder.textView_time.setText(info.getNotepadTime());
return convertview;
}
}
6、在NoteAdapter.java中创建一个 ViewHolder 类来初始化列表子项 Item 界面中的控件。
class ViewHolder
{
TextView textView_things;
TextView textView_time;
View wholeView;
public ViewHolder(View view)
{
textView_things=(TextView) view.findViewById(R.id.things);
textView_time=(TextView) view.findViewById(R.id.time);
wholeView = view;
}
}
完整的NoteAdapter.java文件:
package com.example.mynote;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
//创建 NoteAdapter 类,继承自 BaseAdapter 类。
public class NoteAdapter extends BaseAdapter
{
private List list; //数据准备
private Context mycontext;
private LayoutInflater myinflate; //加载布局视图
//构造函数
public NoteAdapter(Context context,List list)
{
this.list=list;
this.mycontext=context;
this.myinflate=LayoutInflater.from(context);
}
//实现4个方法
@Override
public int getCount()
{ //返回列表长度
return list.size();
}
//根据位置,再去list里面找数据
@Override
public Object getItem(int position)
{ //返回控件
return list.get(position);
}
//返回位置
@Override
public long getItemId(int i)
{ //返回下标
return i;
}
//创一个格子,获取两个控件,填数据
@Override
//参数convertview用于复用列表项布局View,vgroup用于加载列表项xml布局
public View getView(int i, View convertview, ViewGroup vgroup)
{
ViewHolder myholder;
//如果没有空闲的列表项(格子)就新创建一个
if(convertview==null)
{
convertview=myinflate.inflate(R.layout.item,null);
myholder=new ViewHolder(convertview);
convertview.setTag(myholder);
}
else
{
//有列表项(格子)就从里面拿
myholder=(ViewHolder) convertview.getTag();
}
//把getItem(i)第i个位置的内容拿出来
final Bean info=(Bean) getItem(i);
myholder.textView_things.setText(info.getNotepadContent());
myholder.textView_time.setText(info.getNotepadTime());
return convertview;
}
class ViewHolder
{
TextView textView_things;
TextView textView_time;
View wholeView;
public ViewHolder(View view)
{
textView_things=(TextView) view.findViewById(R.id.things);
textView_time=(TextView) view.findViewById(R.id.time);
wholeView = view;
}
}
}
7、创建数据库帮助类 DBSQLiteHelper 实现对数据库创建、数据表的创建。
public class DBSQLiteHelper extends SQLiteOpenHelper
{
public static final String DATABASE_NAME = "Notepad";//数据库名
public static final int DATABASE_VERION = 1; //数据库版本
public static final String DATABASE_NOTEPADTB = "Note"; //记事本数据表名
public static final String NOTEPAD_ID = "id"; //id字段名
public static final String NOTEPAD_CONTENT = "content"; //内容字段名
public static final String NOTEPAD_NOTETIME = "notetime"; //时间字段名
//建表语句
public static final String CREATE_NOTE = "create table Note ("
+ "id integer primary key autoincrement, "
+ "content text, "
+ "notetime text)";
//或以下建表语句
// public static final String CREATE_NOTE = "create table Note ("
// + NOTEPAD_ID+" integer primary key autoincrement, "
// + NOTEPAD_CONTENT+" text, "
// + NOTEPAD_NOTETIME+" text)";
//构造函数
public DBSQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
{
super(context, name, factory, version);
Log.e("SQLiteHelper","construct func2");
}
public DBSQLiteHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERION);
Log.e("SQLiteHelper","construct func");
}
@Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(CREATE_NOTE);
Log.e("SQLiteHelper","onCreate func");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String CREATE_USER = "create table User("+
"id integer primary key autoincrement,"+
"username text,"+
"password text)";
db.execSQL(CREATE_USER);
Log.e("SQLiteHelper","onUpgrade func");
}
}
8、新建DAO.java文件实现对数据库中记录的增删改查,以及获取当前日期。
查询的结果是 List。删除和修改时都需要指定 id。添加时不需要指定 id。为了预防书写错误,可以将数据库的名称、表名、数据库版本、数据库表中 的列名定义为字符串常量
package com.example.mynote;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class DAO
{
private static final String DATABASE_NOTEPADTB = "Note";
public static final String NOTEPAD_ID = "id"; //id字段名
public static final String NOTEPAD_CONTENT = "content"; //内容字段名
public static final String NOTEPAD_NOTETIME = "notetime"; //时间字段名
private DBSQLiteHelper dbOpenHelper;
public DAO(Context context)
{
//创建DBSQLiteHelper对象
dbOpenHelper = new DBSQLiteHelper(context);
//dbOpenHelper.getWritableDatabase(); //创建数据库,可调用,否则在第一次查询时调用
}
//添加数据
public boolean insertData(String userContent,String userTime)
{
//获取数据库对象
SQLiteDatabase sqLiteDatabase = dbOpenHelper.getReadableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(NOTEPAD_CONTENT,userContent);
contentValues.put(NOTEPAD_NOTETIME,userTime);
return sqLiteDatabase.insert(DATABASE_NOTEPADTB,null,contentValues)>0;
}
//删除数据
public boolean deleteData(String id)
{
SQLiteDatabase sqLiteDatabase=dbOpenHelper.getReadableDatabase();
String whereClause = NOTEPAD_ID + "=?";
String[] whereArgs = new String[]{String.valueOf(id)};
return sqLiteDatabase.delete(DATABASE_NOTEPADTB,whereClause,whereArgs)>0;
}
//修改数据
public boolean updateData(String id,String content,String time)
{
SQLiteDatabase sqLiteDatabase=dbOpenHelper.getReadableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(NOTEPAD_CONTENT,content);
contentValues.put(NOTEPAD_NOTETIME,time);
String whereClause = NOTEPAD_ID + "=?";
String[] whereArgs = new String[]{String.valueOf(id)};
return sqLiteDatabase.update(DATABASE_NOTEPADTB,contentValues,whereClause,whereArgs)>0;
}
//查询数据
public List query()
{
SQLiteDatabase sqLiteDatabase=dbOpenHelper.getReadableDatabase();
List list = new ArrayList();
Cursor cursor = sqLiteDatabase.query(DATABASE_NOTEPADTB,null,null,null,
null,null,NOTEPAD_ID+" desc");//按id降序排序
if (cursor.moveToFirst())
{
do{
Bean noteInfo=new Bean();
String id = String.valueOf(cursor.getInt(cursor.getColumnIndex(NOTEPAD_ID)));
String content = cursor.getString(cursor.getColumnIndex(NOTEPAD_CONTENT));
String time = cursor.getString(cursor.getColumnIndex(NOTEPAD_NOTETIME));
noteInfo.setId(id);
noteInfo.setNotepadContent(content);
noteInfo.setNotepadTime(time);
list.add(noteInfo);
}while(cursor.moveToNext());
cursor.close();
}
return list;
}
//获取当前日期,格式化为yyyy年MM月dd日 HH:mm:ss形式的字符串
public static final String getTime()
{
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date date = new Date(System.currentTimeMillis());
return simpleDateFormat.format(date);
}
public void initData()
{
insertData("天气变冷了,记得穿棉衣哦",getTime());
insertData("今天要带小憨猪去外面玩",getTime());
}
}
9、新建Record活动,在点击列表子项和“添加按钮”时跳转该活动。
(1)Record.java文件
package com.example.mynote;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class Record extends AppCompatActivity implements View.OnClickListener {
private ImageView note_back; //返回首页
private TextView noteName; //根据情况显示“添加便签”or“修改便签”
private TextView note_time; //便签修改时间
private EditText content; //便签正文
private ImageView delete; //清除
private ImageView note_save; // 保存
private String id;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.record);
setContentView(R.layout.record);
note_back = (ImageView) findViewById(R.id.note_back);
note_time = (TextView)findViewById(R.id.tv_time);
content = (EditText) findViewById(R.id.note_content);
delete = (ImageView) findViewById(R.id.delete);
note_save = (ImageView) findViewById(R.id.note_save);
noteName = (TextView) findViewById(R.id.note_name);
initData();//根据来源决定顶部显示"添加便签"还是"修改便签"
note_back.setOnClickListener(this); //返回首页
delete.setOnClickListener(this); //清除便签
note_save.setOnClickListener(this); //保存
}
//根据来源决定顶部显示"添加便签"还是"修改便签"
//如果是长按打开显示"修改便签",否则显示"添加便签"
protected void initData()
{
noteName.setText("添加便签");
Intent intent = getIntent();
if(intent!= null)
{
id = intent.getStringExtra("id");
if (id != null)
{ //"修改便签",显示原便签内容
noteName.setText("修改便签");
content.setText(intent.getStringExtra("content"));
note_time.setText(intent.getStringExtra("time"));
//修改显示时间可见,新增不可见
note_time.setVisibility(View.VISIBLE);
}
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.note_back: //返回键功能,关闭当前页面
finish();
break;
case R.id.delete: //“清除按钮”功能:清除编辑框显示
content.setText("");
break;
case R.id.note_save:
String noteContent=content.getText().toString().trim();
if (id != null){//修改操作
if (noteContent.length()>0){
DAO notepadDAO = new DAO(this);
if (notepadDAO.updateData(id, noteContent, notepadDAO.getTime())){
showToast("修改成功");
setResult(1);
finish();
}else {
showToast("修改失败");
}
}else {
showToast("修改内容不能为空!");
}
}else {
//向数据库中添加数据
if (noteContent.length()>0){
DAO notepadDAO = new DAO(this);
if (notepadDAO.insertData(noteContent, notepadDAO.getTime())){
showToast("保存成功");
setResult(1);
finish();
}else {
showToast("保存失败");
}
}else {
showToast("内容不能为空!");
}
}
break;
}
}
public void showToast(String message){
Toast.makeText(Record.this,message,Toast.LENGTH_SHORT).show();
}
}
(2)record.xml文件
<?xml version="1.0" encoding="utf-8"?>
10、修改 MainActivity.java文件,实现备忘录列表显示和新增功能
package com.example.mynote;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;
import java.util.List;
public class MainActivity extends AppCompatActivity{
private ListView listView;
private List notelist;
private DAO notepadDAO;
NoteAdapter adapter;
//在onCreate ()方法中为 ListView 控件设置适配器,适配器的数据源来自数据库表的查询结果
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//用于显示便签的列表
listView = (ListView) findViewById(R.id.listview);
notepadDAO = new DAO(this); //创建 NotepadDAO 对象
notepadDAO.initData();
//下面的if判断可删,就像int n=0,n=3可直接写成int n=3
if (notelist!=null)
{
notelist.clear();
}
//从数据库中查询数据(保存的所有便签)
notelist = notepadDAO.query();//第一次调用,创建数据库
adapter = new NoteAdapter(this, notelist);
//adapter把数据放进去
listView.setAdapter(adapter);
// 为“添加按钮”设置监听器,添加一条备忘录
ImageView add = (ImageView) findViewById(R.id.add);
add.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
Intent intent = new Intent(MainActivity.this,Record.class);
// 给需要传回数据的页面取id
startActivityForResult(intent, 1);
}
});
//单击:打开“修改便签”页面
/*为“添加按钮”通过 setOnClickListener()方法设置监听器,当点击该按钮时,跳转到添加便签的界面。当
添加或修改记录后,记事本首页的列表需要更新显示,因此需要调用 startActivityForResult()根据返回结果决
定是否需要更新列表显示。*/
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent,View view,int position,long id){
Bean notepadBean = notelist.get(position);
Intent intent = new Intent(MainActivity.this, Record.class);
intent.putExtra("id", notepadBean.getId());
intent.putExtra("time", notepadBean.getNotepadTime()); //便签的时间
intent.putExtra("content", notepadBean.getNotepadContent()); //便签的内容
MainActivity.this.startActivityForResult(intent, 1);//修改备忘录
}
});
//长按:打开对话框
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
DialogInterface.OnClickListener listener=new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int pi) {
Bean notepadBean = notelist.get(position);
//根据id删除
notepadDAO.deleteData(notepadBean.getId());
notelist.remove(position);
//刷新
adapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this,"删除成功",Toast.LENGTH_SHORT).show();
}
};
AlertDialog.Builder builder = new AlertDialog.Builder( MainActivity.this);
builder.setTitle("是否删除此备忘录?");
builder.setPositiveButton("确定", listener);
builder.setNegativeButton("取消", null);
builder.show();
return true;
}
});
}
/*当添加或修改返回后:需要刷新首页的 ListView 的显示。可以根据 resultCode 重新设置列表的 Adapter,
刷新显示。*/
@Override
protected void onActivityResult(int requestCode,int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
//都为1表示执行跳转活动且保存数据成功
if (requestCode==1 && resultCode==1)
{ //添加或者更改了备忘录,需要更新显示
//showQueryData();
if (notelist!=null)
{
//清除列表
notelist.clear();
}
//重新查询
notelist = notepadDAO.query();
adapter = new NoteAdapter(this, notelist);
//adapter把数据放进去才会更新,所以上面的if (notelist!=null)……可以不要,重新更新会覆盖以前的
listView.setAdapter(adapter);
}
}
/*初始化显示:可以往数据库(表)中填入一些测试数据,这样在第一次打开 APP 时就可以看到备忘录列
表,初始化显示。方法是:在 NotepadDAO 可以提供 insertData()方法往记事本数据表 Note 中插入若干条
备忘录记录,然后在 MainActivity 中初始化 NotepadDAO 后调用该方法。*/
private void initData(){
notepadDAO.insertData("1今天是五一劳动节",notepadDAO.getTime());
notepadDAO.insertData("2今天心情很美丽",notepadDAO.getTime());
notepadDAO.insertData("3今天要带小乌龟去学校",notepadDAO.getTime());
Log.e("SQLiteHelper","initData func");
}
}
四、相关问题
-
便签记录存放的数据库及表是何时创建的?
DAO层调用helper类
notelist = notepadDAO.query();//第一次调用,创建数据库
public DAO(Context context) { //创建DBSQLiteHelper对象 dbOpenHelper = new DBSQLiteHelper(context); //dbOpenHelper.getWritableDatabase(); //创建数据库,可调用,否则在第一次查询时调用 }
//建表语句 public static final String CREATE_NOTE = "create table Note (" + "id integer primary key autoincrement, " + "content text, " + "notetime text)";
public DBSQLiteHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_NOTE); }
-
打开APP时首页面是如何显示所有的便签的?
//从数据库中查询数据(保存的所有便签) notelist = notepadDAO.query();//第一次调用,创建数据库 adapter = new NoteAdapter(this, notelist); //adapter把数据放进去 listView.setAdapter(adapter);
-
“添加”和“修改”打开活动时有什么不同,是如何处理的?
//根据来源决定顶部显示"添加便签"还是"修改便签" //如果是长按打开显示"修改便签",否则显示"添加便签" protected void initData() { noteName.setText("添加便签"); Intent intent = getIntent(); //看intent是否传回数据 if(intent!= null) { id = intent.getStringExtra("id"); if (id != null) { //"修改便签",显示原便签内容 noteName.setText("修改便签"); content.setText(intent.getStringExtra("content")); note_time.setText(intent.getStringExtra("time")); //修改显示时间可见,新增不可见 note_time.setVisibility(View.VISIBLE); } } }
-
如何实现添加便签和修改便签后刷新主页面的显示?
/*当添加或修改返回后:需要刷新首页的 ListView 的显示。可以根据 resultCode 重新设置列表的 Adapter,
刷新显示。*/
@Override
protected void onActivityResult(int requestCode,int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
//都为1表示执行跳转活动且保存数据成功
if (requestCode==1 && resultCode==1)
{ //添加或者更改了备忘录,需要更新显示
//showQueryData();
if (notelist!=null)
{
//清除列表
notelist.clear();
}
//重新查询
notelist = notepadDAO.query();
adapter = new NoteAdapter(this, notelist);
//adapter把数据放进去才会更新,所以上面的if (notelist!=null)……可以不要,重新更新会覆盖以前的
listView.setAdapter(adapter);
}
}