(3)RecyclerView的实现 ---中间的内容
RecyclerView是一个比ListView更加强大的滚动控件。要使用这个控件需要先在项目的build.gradle中添加RecyclerView库的依赖。这个内容在第一节就讲过,此处按下不表。
然后在布局文件中加入RecyclerView的控件。---->然后新建一个布局文件recycler_item.xml,在这里写RecyclerView的子项布局。
以上布局步骤在前面的小节中已经讲过。现在看看他们的具体实现。

上一节代码讲到:
adapter = new MemoAdapter(MainActivity.this,arr);
StaggeredGridLayoutManager st = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(st);
recyclerView.setAdapter(adapter);
MemoAdapter是一个备忘录适配器,通过这个适配器将arr集合中的数据和RecyclerView联系起来。
怎么联系的呢?
先来看看MemoAdapter这个类。

该类有一个构造方法,三个重写方法,一个内部类,一条注解和一个自定义方法setFiler(List<MemoBean> filterList)。

先看构造方法

//构造器,第一个参数是上下文,第二个参数是传入的带有备忘录所有数据的集合
public MemoAdapter(Context mcontext, List<MemoBean> arr) {
this.mcontext = mcontext;
this.arr = arr;
}

来看内部类:
/*该内部类继承RecyclerView.ViewHolder。然后在ViewHolder的主构造方法中传入一个View参数,
这个参数通常就是RecyclerView子项的最外层布局。
通过这个最外层布局的参数,那么我们就可以通过findViewById()方法来获取布局中各组件的实例了。*/
public class ViewHolder extends RecyclerView.ViewHolder{
TextView item_title,item_content,item_time;
ImageView item_img;
LinearLayout item_layout;
public ViewHolder(@NonNull View itemView) {
super(itemView);
item_title = itemView.findViewById(R.id.item_title);
item_content = itemView.findViewById(R.id.item_content);
item_time = itemView.findViewById(R.id.item_time);
item_img = itemView.findViewById(R.id.item_image);
item_layout = itemView.findViewById(R.id.item_layout);
}
}

来看onCreateViewHolder()方法:第一个参数是要创建的View的父View,第二个参数是要创建的这个View类型。
@NonNull
@Override //该方法是用于创建ViewHolder的实例.
// 在这个布局中将子项布局recycler_item加载进来,然后创建一个ViewHolder的实例,并把加载出来的布局传入构造函数当中,最后将ViewHolder的实例返回。
public MemoAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mcontext).inflate(R.layout.recycler_item,parent,false);
ViewHolder mholder = new ViewHolder(view);
return mholder;
}

 使用LayoutInflater来将recycler_item这个子项加载进来。它的inflate()方法接收三个参数。
第一个参数是:要加载布局文件的id。
第二个参数是:给加载好的布局中添加一个父布局。
第三个参数指定为false,表示只让我们在父布局中声明的layout属性生效,但不会为这个View添加父布局。

来看onBindViewHolder()方法:第一个参数是一个ViewHolder,第二个是位置参数。
@Override                 //该方法用于对RecyclerView子项的数据复制,会在每个子项被滚动到屏幕内的时候执行
public void onBindViewHolder(@NonNull MemoAdapter.ViewHolder mholder, int position) {
final MemoBean memoBean = arr.get(position);
mholder.item_title.setText(memoBean.getTitle());
mholder.item_content.setText(memoBean.getContent());
mholder.item_time.setText(memoBean.getTime());
Glide.with(mcontext).load(memoBean.getImgpath()).into(mholder.item_img);
if(memoBean.getImgpath() ==null){ //如果图片地址为空,则不显示图片
// Toast.makeText(mcontext,"memoBean.getImgpath()"+memoBean.getImgpath(),Toast.LENGTH_LONG).show();
mholder.item_img.setVisibility(View.GONE);
}
  /* 以上代码都是对子项的数据进行赋值,每个子项被滚动到屏幕的时候的时候执行。 */

//长按删除
mholder.item_layout.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
AlertDialog.Builder dialog = new AlertDialog.Builder(mcontext); //弹出一个AlertDialog进行确认。
dialog.setMessage("确定删除吗?");
dialog.setPositiveButton("确定", new DialogInterface.OnClickListener() { //如果点击确认,就从数据库里删除,并从arr集合中移出,然后刷新该页面。
@Override
public void onClick(DialogInterface dialogInterface, int i) {
myDbHelper = new MyDbHelper(mcontext);
database = myDbHelper.getWritableDatabase();
database.delete("tb_memory","_id=?",new String[]{arr.get(position).getId()}); //从数据库里删除
arr.remove(position); //从arr集合中移出
Toast.makeText(mcontext,"删除成功",Toast.LENGTH_LONG).show();
notifyItemChanged(position); //然后刷新该页面,局部刷新,还有其他的刷新方法,这里不讲
dialogInterface.dismiss();
}
});
dialog.setNegativeButton("取消",null);
dialog.setCancelable(false);
dialog.create();
dialog.show();
return false;
}
});

//点击显示
mholder.item_layout.setOnClickListener(new View.OnClickListener() { //如果对子项进行点击,就启动AddInfoActivity,这里我们将该子项的id一起传入AddInfoActivity,因为我们还要在AddInfoActivity中进行判断。
@Override                            //判断什么?在AddInfoActivity中,如果该id存在,那么我们就将该id的内容显示到页面中。如果不存在,那应当是从悬浮按钮点击进入的该Activity,则显示添加页面。
public void onClick(View view) {
Intent intent = new Intent(mcontext, AddInfoActivity.class);
intent.putExtra("_id",arr.get(position).getId());
Toast.makeText(mcontext,"_id"+arr.get(position).getId(),Toast.LENGTH_LONG).show();
startActivity(intent);
}
});

}
来看getItemCount()方法:
public int getItemCount() {
return arr.size();
}
很简单,没啥好说的。

来看ViewHolder这个内部类:
/*该内部类继承RecyclerView.ViewHolder。然后在ViewHolder的主构造方法中传入一个View参数,
这个参数通常就是RecyclerView子项的最外层布局。
通过这个最外层布局的参数,那么我们就可以通过findViewById()方法来获取布局中各组件的实例了。*/
public class ViewHolder extends RecyclerView.ViewHolder{
TextView item_title,item_content,item_time;
ImageView item_img;
LinearLayout item_layout;
public ViewHolder(@NonNull View itemView) {
super(itemView);
item_title = itemView.findViewById(R.id.item_title);
item_content = itemView.findViewById(R.id.item_content);
item_time = itemView.findViewById(R.id.item_time);
item_img = itemView.findViewById(R.id.item_image);
item_layout = itemView.findViewById(R.id.item_layout);
}
}
来看setFiler(List<MemoBean> filterList)方法:
接收一个MemoBean类型的集合,该集合为过滤后的数据,将该集合直接赋值给arr,再刷新界面。
就成功的将搜索的数据展示了出来。
//该方法用于搜索时过滤数据。
public void setFiler(List<MemoBean> filterList){
arr = filterList;
notifyDataSetChanged();
}
以上就是MemoAdapter的全部内容。
好的,再回到MainActivity的那段代码:
adapter = new MemoAdapter(MainActivity.this,arr);
StaggeredGridLayoutManager st = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(st);
recyclerView.setAdapter(adapter);
在这里新建了一个MemoAdapter的适配器adapter。
下一句代码StaggeredGridLayoutManager是什么?
RecyclerView给我们内置了两种布局排列方式:GirdLayoutManager 网格布局
和 StaggeredGridLayoutManager 瀑布流布局

StaggeredGridLayoutManager(布局的列数,布局的排列方向)。
StaggeredGridLayoutManager.VERTICAL表示会让布局纵向排列。

所以recyclerView.setLayoutManager(st);的意思是:指定布局方式为:纵向排列的两行。

最后通过recyclerView.setAdapter(adapter);的方法完成适配器的设置。
(4)SearchView的实现 ---搜索功能
现在我们来看看搜索功能的完整实现。
SearchView是搜索框组件,它可以让用户在文本框内输入汉字,并允许通过监听器监控用户输入,当用户用户输入完成后提交搜索按钮时,也通过监听器执行实际的搜索。
有一个常用的方法setOnQueryTextListener(SearchView.OnQueryTextListener listener):为该搜索框设置事件监听器。我们只需通过该方法即可实现搜索功能。
1.首先,通过绑定控件msearch = findViewById(R.id.search);的方式获取到SearchView组件的对象。
2.继承OnQueryTextListener接口,并实现里面的两个方法。

onQueryTextSubmit(String s):单击搜索按钮时激发该方法。

onQueryTextChange(String s):用户输入字符时激发该方法。

在该方法中调用filter(s)方法。s为用户输入的字符串。

来看看filter(String text)方法:

private List<MemoBean> filter(String text){
filterS = new ArrayList<>();
for(MemoBean memoBean:arr){
if(memoBean.getTitle().contains(text) || memoBean.getContent().contains(text) || memoBean.getTime().contains(text)){
filterS.add(memoBean);
}
}
return filterS;
}
很简单的逻辑,新建了一个MemoBean类型的集合,用于存符合搜索条件的数据,并将其返回。
用for循环遍历arr集合。这个集合里有备忘录的所有内容。如果用户输入的内容 是 集合里的标题,或者内容,或者时间的子字符串,就将该条数据添加给filterS。

回到@Override
public boolean onQueryTextChange(String s) {
filterS = filter(s);
adapter.setFiler(filterS);
return false;
}
现在我们的filterS里装满了符合搜索条件的数据,通过适配器里的setFiler(filterS)方法将页面刷新,将结果显示出来。
2.直接msearch.setOnQueryTextListener(this);

效果图:



(5)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"/>
然后在MainActivity中实现点击跳转就好了:
private void btnOnClicknext(){
btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,AddInfoActivity.class);
startActivity(intent);
finish();
}
});
}
跳转后,启动AddInfoActivity,进入添加备忘录的页面。

-------
源码:https://github.com/Xiang-MY/MemoDemo

RecyclerView + SQLite 简易备忘录-----中(2)的更多相关文章

  1. RecyclerView + SQLite 简易备忘录-----中(1)

    在上一节讲完了登录界面的内容,现在随着Activity的跳转,来到MainActivity. 1.主界面activity_main.xml 由上图,activity_main.xml的内容很简单. 首 ...

  2. RecyclerView + SQLite 简易备忘录-----下

    最后就是添加备忘录的界面了.同时也是显示备忘录内容的界面. 1.activity_add_info.xml 也是比较简陋的一个页面设计. 顶部是一个自定义的Toolbar,剩下的部分都是ScrollV ...

  3. RecyclerView + SQLite 简易备忘录-----上

    先看效果 图一只是做了简单的页面,没有连接数据库,刚写完页面才想起备忘录好像不需要登录------但用SharedPreferences写了个记住密码. 图二是主页面,实现了搜索,添加,删除,修改几个 ...

  4. C# 在SQLite数据库中存储图像 z

    C# 在SQLite数据库中存储图像 更多 0 C# SQLite   建表语句 CREATE TABLE [ImageStore]([ImageStore_Id] INTEGER NOT NULL ...

  5. 将 flask 中的 session 存储到 SQLite 数据库中

    将 flask 中的 session 存储到 SQLite 数据库中 使用 flask 构建服务器后端时,常需要在浏览器端存储 cookie 用于识别不同用户,根据不同的 cookie 判断出当前请求 ...

  6. 网络采集软件核心技术剖析系列(6)---将任意博主的全部博文下载到SQLite数据库中并通过Webbrower显示(将之前的内容综合到一起)

    一 本系列随笔目录及本节代码下载 自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受广大博客写作和阅读爱好者的喜爱.同时也不乏一些技术爱好者咨询我,这个软件里面各种实用的功能是如何实现的. 该软 ...

  7. SQLite数据库中rowid使用

    SQLite数据库中rowid使用   SQLite中每个表都默认包含一个隐藏列rowid,使用WITHOUT ROWID定义的表除外.通常情况下,rowid可以唯一的标记表中的每个记录.表中插入的第 ...

  8. SQLite 3 中的数据类型

    SQLite使用动态类型系统,在SQLite中,值的数据类型和值本身,而不是和它的容器,关联在一起的.SQLite的动态类型系统和其他数据库引擎的静态类型系统是兼容的,这样在静态类型的数据库上执行的S ...

  9. Mysql(或者sqlite), Mongo中update Column + 1

    Mysql(或者sqlite), Mongo中update Column + 1 有类似以下需求,在数据库表里有一个字段,记录了一个count,然后又时候需要在count的基础上加上某个数字,比如1. ...

随机推荐

  1. OO第一单元

    OO第一单元总结 目录 OO第一单元总结 前言 第一次作业 HW1基本思路 UML类图 代码规模 复杂度分析 方法复杂度 分析 类复杂度 分析 优化策略 第二次作业 HW2基本思路 UML类图 代码规 ...

  2. java 学习笔记(一)

    书 head first java 1. 2.加强版的FOR循环 3. 通过super引用父类 4.多态 5.接口和抽象类 接口 6.多线程锁 7.JDBC

  3. github新手使用指南

    常用命令:   Git 速查表(摘自 AI有道) 一.常见命令 git init : 初始化 git 仓库,即将一个文件夹初始化为一个 git 仓库.具体的操作是创建一个 .git 隐藏文件夹 git ...

  4. eclipse启动指定jvm的版本

    参阅:https://www.eclipse.org/forums/index.php/t/1105435/ https://wiki.eclipse.org/Eclipse.ini#-vm_valu ...

  5. SpringMvc中函数的返回值是什么?

    返回值可以有很多类型,有String, ModelAndView.ModelAndView类把视图和数据都合并的一起的,但一般用String比较好.

  6. Error和Exception有什么区别?

    Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题:比如内存溢出,不可能指望程序能处理这样的情况:Exception表示需要捕捉或者需要程序进行处理的异常, ...

  7. Dubbo telnet 命令能做什么?

    dubbo 服务发布之后,我们可以利用 telnet 命令进行调试.管理. Dubbo2.0.5 以上版本服务提供端口支持 telnet 命令 连接服务 telnet localhost 20880 ...

  8. 分布式集群中为什么会有 Master?

    在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机 器可以共享这个结果,这样可以大大减少重复计算,提高性能,于是就需要进行 leader 选举.

  9. SQL数据库之设置查询出来数据为默认值

    -- 如果工资为null,按0处理 -- 函数: ifnull(字段, 默认值) : 如果指定字段的内容是null, 就按默认值处理 select name, ifnull(salary, 0) fr ...

  10. 《基于.NET Core构建微服务》系列文章(更新至第6篇,最新第7篇,已发布主页候选区)

    原文:Building Microservices On .NET Core – Part 1 The Plan 时间:2019年1月14日 作者:Wojciech Suwała, Head Arch ...