RecyclerView + SQLite 简易备忘录-----中(1)
在上一节讲完了登录界面的内容,现在随着Activity的跳转,来到MainActivity。
1.主界面activity_main.xml

由上图,activity_main.xml的内容很简单。
首先是定义了一个androidx.appcompat.widget.Toolbar。先来看看,什么是Toolbar。这是由AndroidX库提供的一个控件。
看Toolbar之前,先来看看ActionBar。ActionBar是什么?其实每个Activity最顶部的标题栏就是ActionBar,不过系统原生的ActionBar由于其设计的原因,被限定只能用于顶部,从而不能实现一些Material Design的效果,官方不再建议用ActionBar,更推荐使用Toolbar。
Toolbar不仅继承了ActionBar的所有功能,还可以配合控件完成一些Material Design的效果。
现在我们准备使用Toolbar来替代ActionBar,因此需要指定一个不带ActionBar的主题。在res\values\themes.xml下,将parent设置为"Theme.AppCompat.Light.NoActionBar"

然后就可以设置Toolbar了。此处是将搜索放在了toolbar里面。
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:textColor="#CCCCCC"
android:text="Memo"
android:textSize="22dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<SearchView
android:iconifiedByDefault="false"
android:id="@+id/search"
android:background="@drawable/corners_shade_2"
android:imeOptions="actionSearch"
android:layout_width="270dp"
android:layout_height="30dp"/>
</androidx.appcompat.widget.Toolbar>
由上,SearchView为android提供的搜索组件。来看看它的属性吧。
android:iconifiedByDefault="false" ---> 这个属性默认为true,设置为false时,直接展开显示左侧有放大镜,右侧无叉叉;有输入内容后,右侧叉叉显示出来。
android:imeOptions="actionSearch" --->键盘右下角的键设置。actionNone:没有动作;actionSearch:去搜索;actionSend:发送;actionGo:去往。
现在来看一下悬浮按钮FloatingActionButton.(也是下文中的FAB)
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btn_add"
android:src="@drawable/add"
app:fabSize="normal"
android:backgroundTint="#66CCCC"
android:elevation="5dp"
app:rippleColor="#66CCCC"
android:layout_gravity="bottom|right"
android:layout_margin="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
来看看它的属性。
app:fabSize="normal" --->设置FAB的大小,可选的值有三个;mini normal auto.
android:backgroundTint="#66CCCC" --->设置FAB的整体背景,如果没有设置,默认会取theme中的colorAccent作为背景色;
android:elevation="5dp" --->FAB在z轴方向的距离,也就是海拔深度,实际效果就是阴影效果;
app:rippleColor="#66CCCC" --->点击Fab时出现水波纹扩散的效果;
最后是RecyclerView.
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_marginTop="60dp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
由上,在activity_main.xml放了一个RecyclerView,对于它的item放在了recycler_item.xml里面。

由上图,为recycler_item.xml的效果,整个布局只有ShapeableImageView需要讲解一下。
可以看到,该组件只有最后的app:shapeAppearanceOverlay="@style/eggStyle"/>和android:scaleType="centerCrop"不同,前者与上一节中activity_login.xml中一样,具体不再阐述。
后者scaleType="centerCrop"的意思是:以原图填满ImageView为目的,如果原图size大于ImageView的size,则与center_inside一样,按比例缩小,居中显示在ImageView上。如果原图size小于ImageView的size,则按比例拉升原图的宽和高,填充ImageView居中显示。
该标签还有很多值,具体可百度。
剩下的三个TextView分别是标题,内容和时间。在内容这一块的TextView中,
<TextView
android:layout_marginTop="5dp"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:id="@+id/item_content"
android:ellipsize="end"
android:maxLines="3"
android:textColor="#CCCCCC"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
由上,有两个标签需要解释下。
android:ellipsize="end" --->当文字过长时,省略号显示在结尾。有四个值:start end middle marquee(以跑马灯的方式显示)
android:maxLines="3" --->显示的行数最大为3行,与ellipsize标签搭配使用。表示,最多显示三行的内容,剩下的内容用...表示。
2.主界面MainActivity
(1)ToolBar的实现 ----顶部菜单栏
这一步很简单,首先通过setSupportActionBar(findViewById(R.id.toolbar));将我们自定义的toolbar实例传入。这时的标题栏什么都没有,我们可以对它进行一些修改,
1.修改标题栏显示的文字。
直接在AndroidManifest.xml中指定,
由上图,通过android:label=" "进行指定。
2.为菜单栏增加一些action按钮。

由上图红色矩形框出来的部分,我们可以在MainActivity中实现这样的效果。
步骤:1):在res目录下创建menu文件夹。然后新建Menu resource file命名为main。名字自己取。
2):编写代码。如上图编写<item /> 此处还有一个标签app:showAsAction。但是我没有在这个menu中写出来,我在添加的界面写了,应该是下几节的内容,但放在这块儿一起讲了。
新建一个Menu resource file命名为add。为它编写的代码如下。
我们为第一个item添加了app:showAsAction="ifRoom"和android:icon="@drawable/skin"标签。icon就不用解释了,来说说showAsAction。
这个标签主要有以下几种值可选:always :表示永远显示在Toolbar中。如果屏幕不够则不显示。
ifRoom: 表示屏幕空间足够的情况下显示在Toolbar中,不够就显示在菜单当中。
never: 表示永远显示在菜单当中。
注意:Toolbar中action按钮只会显示图标,菜单当中的action按钮只会显示文字。
3.创建菜单,加载main.xml文件。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main,menu);
return true;
}
4.设置这些action的点击事件
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
return super.onOptionsItemSelected(item);
}
此处的点击事件我没有写,但是在添加备忘录的Activity有写,是为了插入图片到备忘录。此处先略过,后面会讲。
(2)SQLite的实现 ----将备忘录内容存到数据库
SQLite这是Android内置的一个数据库。Android为了让我们能够更加方便的管理数据库,专门提供了一个SQLiteOpenHelper帮助类,借助这个类可以非常简单地对数据进行创建和升级。
SQLiteOpenHelper是一个抽象类,所以需要创建一个自己的帮助类去继承它。它有两个抽象方法,onCreate()和onUpgrade()。
必须在自己的帮助类里重写这两个方法,然后分别在这两个方法里实现数据库的创建和升级的逻辑。
SQLiteOpenHelper还有两个非常重要的实例方法:getReadableDatabase()和getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则就创建一个新的数据库)
并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式打开数据库,而getWritableDatabase()将会抛出异常。
构造方法:接收4个参数。第一个参数是Context;第二个参数是数据库名;第三个参数允许我们在查询数据的时候返回一个自定义的Cursor,一般传入null。
第四个参数表示当前的版本号,用于对数据库进行升级操作。
public class MyDbHelper extends SQLiteOpenHelper {
private static String DBNAME = "memodemo.db"; //数据库名称
private static int VERSION = 1; //版本号
public MyDbHelper(Context context) { //构造方法
super(context,DBNAME,null,VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) { //创建数据库
sqLiteDatabase.execSQL("create table tb_memory(_id Integer primary key,titel String(200),content String,imgpath String,mtime String)");
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { //数据库升级,此处我没写。
}
}
在以上的代码中,创建了一个名叫"memodemo.db"的数据库,在该数据库中,新建了一张名为tb_memory的表,表里有_id,titel,content,imgpath,mtime五个字段。(title这个单词写错了,但是我后面才发现,就懒得改了。)
可以通过 MyDbHelper myDbHelper = new MyDbHelper(MainActivity.this);
SQLiteDatabase database = myDbHelper.getWritableDatabase();
database.insert(“表名”,null,contentValues对象)。这是向表中插入数据的代码。只需将要插入的数据放在contentValues对象里即可。
ContentValues contentValues = new ContentValues();
contentValues.put("titel",title);
contentValues.put("content",content);
contentValues.put("imgpath",disp_path);
contentValues.put("mtime",time.year + "/" + (time.month + 1) + "/" +time.monthDay);
注意顺序,应该先创建contentValues对象放数据,再调用insert()方法插入。
更新数据时,先将要更新的数据放在contentValues对象中,然后通过database.update("tb_memory",contentValues,"_id = ?",new String[]{myid});的方式更新。
第一个参数是表名,第二个参数是contentValues对象,第三个参数是具体更新哪条数据,此处用了"_id = ?"的方式,表示更新所有_id=?的行,?在这里是占位符,可以通过第四个参数提供的一个字符串数组为第三个参数中的每个占位符指定相应的内容。
删除数据时,通过database.delete("tb_memory","_id=?",new String[]{arr.get(position).getId()});的方式进行删除。
第一个参数是表名,第二个,第三个参数同更新数据时的后两位参数同理。
查询数据库时,通过rawQuery()方法进行数据查询,还有query()方法。
rawQuery()方法:
Cursor cursor = database.rawQuery("select * from tb_memory",null); --->第一个参数是sql的select语句,第二个参数是select语句中占位符参数的值。如果没有占位符,可以设置为null。
我写的这条没有占位符,所有第二个参数用的null。有占位符的例子:
Cursor cursor = db.rawQuery("select * from person where name like ? and age=?", new String[]{"李华", "4"});
来看看此处是完整代码:
private void recyDisplay(){
MemoBean memoBean;
Cursor cursor = database.rawQuery("select * from tb_memory",null);
while (cursor.moveToNext()){
String myid = cursor.getString(cursor.getColumnIndex("_id"));
String mytitle = cursor.getString(cursor.getColumnIndex("titel"));
String mycontent = cursor.getString(cursor.getColumnIndex("content"));
String mytime = cursor.getString(cursor.getColumnIndex("mtime"));
String myimgpath = cursor.getString(cursor.getColumnIndex("imgpath"));
memoBean = new MemoBean(myid,mytitle,mycontent,myimgpath,mytime);
arr.add(memoBean);
}
cursor.close();
adapter = new MemoAdapter(MainActivity.this,arr);
StaggeredGridLayoutManager st = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(st);
recyclerView.setAdapter(adapter);
}
首先,MemoBean是什么?
这是我写的一个关于备忘录的类。先来看看这个类:

为了截图,我把空行删了,看着不太美观,但不影响。可以看到这里面的属性与表的字段一致,都是备忘录的属性。
回到上面的代码,我们创建了一个MemoBean的对象,memoBean,然后我们通过while循环,查询tb-memory这张表里的所有数据,将这些数据通过memoBean的构造方法,返回一个拥有这些信息的memoBean。好像说绕了,也就是说,表里的每条数据都是一个memoBean,每个memoBean都拥有自己的id,标题,内容,图片地址,时间。
arr是什么?List<MemoBean> arr = new ArrayList<>(); arr是一个用于存放MemoBean类型数据的集合。将所有的memoBean添加到arr中。
退出循环时,arr中已经添加完数据库中所有的数据。然后关闭游标。
下一行代码:adapter = new MemoAdapter(MainActivity.this,arr);
问题来啦,MemoAdapter(MainActivity.this,arr);是什么?
这段代码理解为:通过 MemoAdapter的构造方法新建了一个adapter对象。我们给这个构造方法传入两个参数。
第一个参数是上下文,第二个是添加了备忘录所有数据的arr。
MemoAdapter--备忘录适配器,是什么?干什么的?那么接下来的问题就涉及到第三点RecyclerView了。
-----------
源码:https://github.com/Xiang-MY/MemoDemo
RecyclerView + SQLite 简易备忘录-----中(1)的更多相关文章
- RecyclerView + SQLite 简易备忘录-----中(2)
(3)RecyclerView的实现 ---中间的内容 RecyclerView是一个比ListView更加强大的滚动控件.要使用这个控件需要先在项目的build.gradle中添加RecyclerV ...
- RecyclerView + SQLite 简易备忘录-----下
最后就是添加备忘录的界面了.同时也是显示备忘录内容的界面. 1.activity_add_info.xml 也是比较简陋的一个页面设计. 顶部是一个自定义的Toolbar,剩下的部分都是ScrollV ...
- RecyclerView + SQLite 简易备忘录-----上
先看效果 图一只是做了简单的页面,没有连接数据库,刚写完页面才想起备忘录好像不需要登录------但用SharedPreferences写了个记住密码. 图二是主页面,实现了搜索,添加,删除,修改几个 ...
- C# 在SQLite数据库中存储图像 z
C# 在SQLite数据库中存储图像 更多 0 C# SQLite 建表语句 CREATE TABLE [ImageStore]([ImageStore_Id] INTEGER NOT NULL ...
- 将 flask 中的 session 存储到 SQLite 数据库中
将 flask 中的 session 存储到 SQLite 数据库中 使用 flask 构建服务器后端时,常需要在浏览器端存储 cookie 用于识别不同用户,根据不同的 cookie 判断出当前请求 ...
- 网络采集软件核心技术剖析系列(6)---将任意博主的全部博文下载到SQLite数据库中并通过Webbrower显示(将之前的内容综合到一起)
一 本系列随笔目录及本节代码下载 自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受广大博客写作和阅读爱好者的喜爱.同时也不乏一些技术爱好者咨询我,这个软件里面各种实用的功能是如何实现的. 该软 ...
- SQLite数据库中rowid使用
SQLite数据库中rowid使用 SQLite中每个表都默认包含一个隐藏列rowid,使用WITHOUT ROWID定义的表除外.通常情况下,rowid可以唯一的标记表中的每个记录.表中插入的第 ...
- SQLite 3 中的数据类型
SQLite使用动态类型系统,在SQLite中,值的数据类型和值本身,而不是和它的容器,关联在一起的.SQLite的动态类型系统和其他数据库引擎的静态类型系统是兼容的,这样在静态类型的数据库上执行的S ...
- Mysql(或者sqlite), Mongo中update Column + 1
Mysql(或者sqlite), Mongo中update Column + 1 有类似以下需求,在数据库表里有一个字段,记录了一个count,然后又时候需要在count的基础上加上某个数字,比如1. ...
随机推荐
- (leetcode)二叉树的层次遍历-c语言实现
这段代码,在后面跑测试用例时,出现了stack-overflow,但是原因还不清楚. 问题如下: 二叉树的层次遍历 给定一个二叉树,返回其按层次遍历的节点值. (即逐层地,从左到右访问所有节点) ...
- 《前端运维》三、Docker--1镜像与容器
一.基本概念 如果我们想要让软件运行起来,首先要保证操作系统的设置,其次还需要依赖各种组件和库的正确安装.那么虚拟机就是一种带环境安装的一种解决方案,它可以实现在一种操作系统里面运行另外一种操作系统, ...
- C# XML基础入门(XML文件内容增删改查清)
前言: 最近对接了一个第三方的项目,该项目的数据传输格式是XML.由于工作多年只有之前在医疗行业的时候有接触过少量数据格式是XML的接口,之后就几乎没有接触过了.因此对于XML这块自己感觉还是有很多盲 ...
- linux下串口测试程序
通过简单的参数配置,执行文件+串口号+波特率 #include <stdio.h> #include <stdlib.h> #include <unistd.h> ...
- MySQL 数据库作发布系统的存储,一天五万条以上的增量, 预计运维三年,怎么优化?
1.设计良好的数据库结构,允许部分数据冗余,尽量避免 join 查询,提高效率. 2.选择合适的表字段数据类型和存储引擎,适当的添加索引. 3.MySQL 库主从读写分离. 4.找规律分表,减少单表中 ...
- 什么是 JavaConfig?
Spring JavaConfig 是 Spring 社区的产品,它提供了配置 Spring IoC 容器的纯 Java 方法.因此它有助于避免使用 XML 配置.使用 JavaConfig 的优点在 ...
- EMQX_AUTH_USERNAME 使用
emqx_auth_username 它通过比对每个终端的接入的 username 和 password 与 EMQ X 中存储的是否一致来实现终端接入的控制.其功能逻辑如下: emqx_auth_u ...
- 数组有没有length()方法?String有没有length()方法?
数组没有length()方法,有length 的属性.String 有length()方法.JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆.
- 什么是 Aspect?
aspect 由 pointcount 和 advice 组成, 它既包含了横切逻辑的定义, 也包 括了连接点的定义. Spring AOP 就是负责实施切面的框架, 它将切面所定义的横 切逻辑编织到 ...
- 基于Python3实现的各类数据库连接和连接池
基于Python3的各类数据库连接和连接池, 支持数据库有: Mysql(MariaDB), Oracle, PostgreSQL(GreenPlum), Vertica, Redis, MongoD ...

