俺的碎碎念:写了个简单的记事本APP 复习了下SQLite的使用以及各种边角知识,希望能对各位带来一定的启发。

        功能简介:本项目实现了记事本的基本功能,支持创建笔记,编辑笔记,长按删除笔记等功能;后续新增功能也会同步更新到博客和公众号。

主要功能演示:

创建新笔记:

编辑笔记:

删除笔记:

本项目的笔记APP核心的存储逻辑是基于SQLite数据库开发的,说白了就是增删改查的简单封装和使用。

思路也比较简单,RecycleView负责展示对应的笔记列表,而实际的存储是依靠SQLite。

废话不多说来看下关键代码。

SQLite数据库代码讲解 

DBUtils工具类代码如下:

//工具类的存在主要是为了创建Helper文件时 引用的数据库参数更加便捷,使逻辑更清楚。
public class DBUtils {public static final String SQL_NAME = "Notepad.db";//数据库名public static final String SQL_TABLE = "notemane";//表名public static final int DATABASE_VERSION = 1;//数据库版本//数据库表中的列名public static final String NOTEPAD_ID = "id";public static final String NOTEPAD_CONTENT = "content";//item内容public static final String NOTEPAD_TIME = "time";//item的修改时间public static final String NOTEPAD_TITLE = "title";//标题//获取时间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);}}

Android 提供了抽象类SQLiteOpenHelper来帮助我们使用SQLite数据库,如果我们想要使用SQLite数据库,那么就必须新建一个Helper类来继承SQLiteOpenHelper这个抽象类。

SQLiteHelper代码如下:

public class SQLiteHelper extends SQLiteOpenHelper {SQLiteDatabase mSQLiteDatabase;public SQLiteHelper(Context context) {super(context, DBUtils.SQL_NAME, null, DBUtils.DATABASE_VERSION);mSQLiteDatabase = this.getWritableDatabase();//在数据库创建时即允许写入}/*** 构造函数** @param context* @param name* @param factory* @param version* @param errorHandler*/public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {super(context, name, factory, version, errorHandler);}public SQLiteHelper(Context context, String name, int version, @NonNull SQLiteDatabase.OpenParams openParams) {super(context, name, version, openParams);}@Overridepublic void onCreate(SQLiteDatabase db) {//创建表String sql = "create table notemane(id integer primary key autoincrement,content varchar(20),time varchar(20),title varchar(20))";db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}//增public boolean insertDate(String userContent, String userTime, String userTitle) {mSQLiteDatabase = this.getWritableDatabase();//允许写入ContentValues values = new ContentValues();values.put(DBUtils.NOTEPAD_CONTENT, userContent);values.put(DBUtils.NOTEPAD_TIME, userTime);values.put(DBUtils.NOTEPAD_TITLE, userTitle);return mSQLiteDatabase.insert(DBUtils.SQL_TABLE, null, values) > 0;}//删public boolean deleteData(String id) {mSQLiteDatabase = this.getWritableDatabase();//允许写入String sql = DBUtils.NOTEPAD_TIME + "=?";//删除是根据时间删除的,也可以根据id删除,但是根据id删除要考虑到recycleView的position会变化String[] contentValues = new String[]{String.valueOf(id)};return mSQLiteDatabase.delete(DBUtils.SQL_TABLE, sql, contentValues) > 0;}//改public boolean updateData(String id, String userTitle, String userContent, String userTime) {mSQLiteDatabase = this.getWritableDatabase();//允许写入ContentValues values = new ContentValues();values.put(DBUtils.NOTEPAD_TITLE, userTitle);values.put(DBUtils.NOTEPAD_CONTENT, userContent);values.put(DBUtils.NOTEPAD_TIME, userTime);String sql = DBUtils.NOTEPAD_ID + "=?";String[] strings = new String[]{id};return mSQLiteDatabase.update(DBUtils.SQL_TABLE, values, sql, strings) > 0;}}

主界面代码讲解

主界面的主要功能是展示笔记列表,列表这里我选用的是RecycleView。

RecycleView的使用流程: 在主布局中引用RecycleView控件 -> 搭建RecycleView中item的布局 -> 搭建RecycleView的适配器 -> 在MainActivity中使用。

RecycleViewAdapter代码如下:

public class RecycleViewAdapter extends RecyclerView.Adapter<RecycleViewAdapter.ViewHolder> {private static final String TAG = "RecycleViewAdapter";Context mContext;private ArrayList<NoteMessageBean> mList;NoteMessageBean mNoteMessageBean = new NoteMessageBean();//笔记的bean类onRecycleItemClickListener monRecycleItemClickListener;onRecycleItemCheckChangeListener mRecycleItemCheckChangeListener;//构造函数,一个参数public RecycleViewAdapter(Context mContext) {this.mContext = mContext;}//构造函数,两个参数public RecycleViewAdapter(Context mContext, ArrayList<NoteMessageBean> mList) {this.mContext = mContext;this.mList = mList;}@Overridepublic RecycleViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycle_item, parent, false);return new ViewHolder(itemView);}@Overridepublic void onBindViewHolder(RecycleViewAdapter.ViewHolder holder, int position) {mNoteMessageBean = (mList.get(position));holder.text.setText(mNoteMessageBean.getContent());//每个item中的简单介绍holder.title.setText(mNoteMessageBean.getTitle());//每个item中的标题holder.time.setText(mNoteMessageBean.getmTime());//每个item中的时间holder.itemView.setOnClickListener(v -> {if (monRecycleItemClickListener != null) {NoteMessageBean messageBean = mList.get(position);Log.d(TAG, "onBindViewHolder-> itemView -> onClick: " + position + messageBean.getTitle() + messageBean.getContent() + messageBean.getmTime());monRecycleItemClickListener.onItemClick(messageBean.getId(), messageBean.getTitle(), messageBean.getContent(), messageBean.getmTime());}});holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {@Overridepublic boolean onLongClick(View v) {if (mRecycleItemCheckChangeListener != null) {holder.mCheckBox.setVisibility(View.VISIBLE);}return true;}});holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {Log.d(TAG, "onCheckedChanged: !isChecked" + isChecked);if (!isChecked) {buttonView.setChecked(false);//从选中 -> 未选中状态} else {buttonView.setChecked(true);//从未选中 -> 选中状态//当选中CheckBox时 弹出弹窗提示 是否删除Dialog mDialog = new Dialog(mContext, R.style.ThemeOverlay_AppCompat_Dialog);View view = View.inflate(mContext, R.layout.delete_dialog, null);ImageView mImageView = (ImageView) view.findViewById(R.id.delete_item_image);mDialog.setContentView(view);mDialog.setCanceledOnTouchOutside(false);mDialog.show();Window window = mDialog.getWindow();window.setContentView(view);window.setGravity(Gravity.BOTTOM);WindowManager.LayoutParams lp = mDialog.getWindow().getAttributes();lp.width = WindowManager.LayoutParams.MATCH_PARENT; //设置宽度lp.height = WindowManager.LayoutParams.WRAP_CONTENT; //设置宽度mDialog.getWindow().setAttributes(lp);mDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {@Overridepublic void onCancel(DialogInterface dialog) {//如果手势操作返回键 取消了弹窗显示//则 弹窗取消显示时 对 CheckBox进行隐藏holder.mCheckBox.setChecked(false);holder.mCheckBox.setVisibility(View.GONE);}});//点击删除图标mImageView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {NoteMessageBean messageBean = mList.get(position);mRecycleItemCheckChangeListener.onImageViewOnClick((messageBean.getmTime()), position);mDialog.dismiss();holder.mCheckBox.setVisibility(View.GONE);holder.mCheckBox.setChecked(false);notifyDataSetChanged();}});}}});//这里是给不同的item设置不同的颜色//用position的个位数进行约束int mNumber = position % 10;Log.d(TAG, "onBindViewHolder: " + mNumber);switch (mNumber) {case 0:case 6:holder.itemView.setBackgroundResource(R.drawable.shape_rounded_corners);break;case 1:case 7:holder.itemView.setBackgroundResource(R.drawable.itemstyle0);break;case 2:case 8:holder.itemView.setBackgroundResource(R.drawable.itemstyle1);break;case 3:case 9:holder.itemView.setBackgroundResource(R.drawable.itemstyle2);break;case 4:holder.itemView.setBackgroundResource(R.drawable.itemstyle3);break;case 5:holder.itemView.setBackgroundResource(R.drawable.itemstyle4);break;}}@Overridepublic int getItemCount() {return mList.size();//item数量}/*** 为列表设置数据源** @param data*/public void setList(ArrayList<NoteMessageBean> data) {this.mList = data;notifyDataSetChanged();}public class ViewHolder extends RecyclerView.ViewHolder {private TextView title, text, time;private ConstraintLayout mLinearLayout;private CheckBox mCheckBox;public ViewHolder(View itemView) {super(itemView);text = itemView.findViewById(R.id.text_note);title = itemView.findViewById(R.id.title_note);time = itemView.findViewById(R.id.time_note);mLinearLayout = itemView.findViewById(R.id.item_layout);mCheckBox = itemView.findViewById(R.id.radioButton);}}/*** RecycleView的点击回调*/public interface onRecycleItemClickListener {void onItemClick(String id, String Title, String content, String time);}public void setOnItemClickListener(onRecycleItemClickListener listener) {monRecycleItemClickListener = listener;}/*** 删除动作的回调*/public interface onRecycleItemCheckChangeListener {void onImageViewOnClick(String time, int position);}public void setOnItemLongClickListener(onRecycleItemCheckChangeListener listener) {mRecycleItemCheckChangeListener = listener;}}

RecycleView在MainActivity中使用流程如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener, RecycleViewAdapter.onRecycleItemClickListener, RecycleViewAdapter.onRecycleItemCheckChangeListener {private RecycleViewAdapter mAdapter;
private LinearLayoutManager manager;
private RecyclerView mRecyclerView;@Overrideprotected void onCreate(Bundle savedInstanceState) {Log.d(TAG, "onCreate: ");super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView() {mRecyclerView = findViewById(R.id.recycler_view);mAdapter = new RecycleViewAdapter(this, mList);mAdapter.setOnItemClickListener(this);mAdapter.setOnItemLongClickListener(this);manager = new LinearLayoutManager(getApplicationContext());mRecyclerView.setLayoutManager(manager);mRecyclerView.setAdapter(mAdapter);}//代码篇幅略长,仅展示RecycleView在MainActivity如何使用}

编辑界面代码讲解

编辑界面的主要功能:1.新建笔记时写入内容标题等。2.打开笔记时对原有笔记进行修改。

其主要的布局为EditText。

编辑界面主要代码如下:

public class EditActivity extends AppCompatActivity implements View.OnClickListener {private static final String TAG = "EditActivity";private ImageView mBack, mCommit;private EditText mTitle, mContent;private TextView mTime;private SQLiteHelper mSQLiteHelper;private Context mContext;private boolean flag;private String id;protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.edit_activity_layout);initView();initData();}private void initView() {mBack = findViewById(R.id.bt_back);mBack.setOnClickListener(this);mCommit = findViewById(R.id.bt_commit);mCommit.setOnClickListener(this);mTitle = findViewById(R.id.edit_title);mContent = findViewById(R.id.edit_text);mTime = findViewById(R.id.time_date);}private void initData() {Log.d(TAG, "initData: ");mSQLiteHelper = new SQLiteHelper(getApplicationContext());mTime.setText(DBUtils.getTime());Intent intent = getIntent();flag = intent.getBooleanExtra("flag", false);//以flag为基准,有且仅有点击item之后才会调用 intent.putExtra("flag", true);if (flag) {id = intent.getStringExtra("id");mTitle.setText(intent.getStringExtra("title"));mContent.setText(intent.getStringExtra("content"));mTime.setText(intent.getStringExtra("time"));}}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.bt_back:Intent intent = new Intent(EditActivity.this, MainActivity.class);startActivity(intent);break;case R.id.bt_commit:if (mContent.length() == 0) {//当内容为空时,提醒一下,不创建新的itemToast.makeText(this.getApplicationContext(), "请输入文本内容后再进行提交操作!", Toast.LENGTH_SHORT).show();} else {if (flag) {//为true表示现在是打开了一个item进行修改编辑 并不是新建笔记mSQLiteHelper.updateData(id, mTitle.getText().toString(), mContent.getText().toString(), mTime.getText().toString());//更新数据后 跳转到MainActivity页面刷新数据Intent mIntent = new Intent(EditActivity.this, MainActivity.class);startActivity(mIntent);} else {//内容不为空则调用对应的数据库插入操作mSQLiteHelper.insertDate(mContent.getText().toString(), DBUtils.getTime(), mTitle.getText().toString());//插入数据之后 跳转到main页面 更新列表视图Intent mIntent = new Intent(EditActivity.this, MainActivity.class);startActivity(mIntent);}}break;}}}

至此,笔记APP的基本功能完成,扩展功能目前的计划加入 手写输入功能,图片插入功能,语音输入功能,搜索功能。

扩展功能以及源码我会逐渐更新在公众号中(二两仙气儿),毕竟我也不能一直摸鱼(狗头)。

从无到有,一步一步实现记事本APP(一)相关推荐

  1. 从无到有,一步一步实现记事本APP(二)

    在上一篇文章中,我们已经实现了记事本APP的基本功能,本篇文章主要介绍如何实现手写板功能,以及手写素材如何保存. 手写板(手写输入/涂鸦)实现的大致思路如下:设置固定颜色的画板 -> 监听Tou ...

  2. 一步一步教你玩转.NET Framework的配置文件app.config (转载)

    一步一步教你玩转.NET Framework的配置文件app.config 在一般的项目中,为了使你的代码更加灵活,更方便调整,减少不必要的hard code,我们都在config中添加许多配置信息, ...

  3. android一步一步实现视频客户端app(一)

    我开发完成了一个完整的视频客户端app,现在,分享出来,供初学者学习参考(大神就不用看了,比较简单,仅供入门),大家相互交流相互学习.项目有些功能,我时间也不是很多,只能时不时更新下.只能大概讲解怎么 ...

  4. android记事本报告,百度云记事本app交互体验报告

    体验设备 体验产品:百度云记事本app 产品版本:Android  V 2.1.1 体验机型:三星Note2 操作系统:Android4.3 体验时间:2016.01.25-2016.01.30 整体 ...

  5. 一步一步教你在 Android 里创建自己的账号系统(一)

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 大家在 ...

  6. 一步一步学Silverlight 2系列(18):综合实例之RSS阅读器

    概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...

  7. 手挽手带你学React:四档(上)一步一步学会react-redux (自己写个Redux)

    手挽手带你学React入门四档,用人话教你react-redux,理解redux架构,以及运用在react中.学完这一章,你就可以开始自己的react项目了. 之前在思否看到过某个大神的redux搭建 ...

  8. 一步一步学Silverlight 2系列(9):使用控件模板

    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://terrylee.blog.51cto.com/342737/67243 ...

  9. 据lovecherry的一步一步学Remoting序列文章学习.net Remoting日记(2)

    今天学习了服务器端激活和客户端激活的区别!可还是出现了一点点的差错,经过对比得到正确的调用方法,整理如下: 1.服务器端激活,分为两种方式Singleton和SingleCall方式 Server端A ...

最新文章

  1. 运行VC++6.0出现error LNK2001: unresolved external symbol _WinMain@16
  2. python的垃圾回收机制和析构函数__del__
  3. dump导入oracle需要提前建表吗_数据库dump导入
  4. OCR-PIL.Image与Base64 String的互相转换
  5. c语言打印空心等腰梯形乐学,C语言做激光发射
  6. PHP双码率视频云转码服务网站源码 支持M3u8秒切
  7. VMware vSphere第三方免费工具介绍之一:RVTools
  8. Power BI 与 Azure Analysis Services 的数据关联:4、Power BI 连接到Azure Analysis Services 并展示...
  9. 国内四大炒股软件APP 全面技术解析
  10. 从零开始制作PPT(母版设计,素材填充,配色等)
  11. TensorFlow: A System for Large-Scale Machine Learning翻译
  12. 03、集合之ArrayList
  13. 【Linux常用服务器配置——Samba服务】
  14. Unity Metaverse(四)、接入环信IM SDK 实现用户登录注册
  15. 占带宽测试软件,铁通网速测试
  16. scrapy实现链家二手房的数据获取并进行持久化存储
  17. 2022-2028年中国银行保险市场投资分析及前景预测报告
  18. PHP反序列化与SESSION
  19. 宅急送项目第三天笔记!(SVN插件和反编译插件)
  20. 从XData大数据一体机看曙光转型

热门文章

  1. 异构:1并行计算盖伦
  2. 您的ISCSI够快吗?
  3. 多媒体系统之MediaCodec基本原理及使用
  4. android textview 长按事件,利用TextView怎么实现一个长按复制功能
  5. matlab画地震复杂模型,复杂速度模型,可用于地震旅行时计算(FMM)
  6. phpcms之 如何把自己的静态模板套入到phpcms模板
  7. 二手小米手机价格查询
  8. java视频超清,JavaWeb合集第二阶段(后端篇)学习视频-超清4k画质
  9. 硬盘测试工具 hdparm
  10. 天猫上不靠谱的商品价格