RecyclerView + SQLite 简易备忘录-----中(2)
(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)的更多相关文章
- RecyclerView + SQLite 简易备忘录-----中(1)
在上一节讲完了登录界面的内容,现在随着Activity的跳转,来到MainActivity. 1.主界面activity_main.xml 由上图,activity_main.xml的内容很简单. 首 ...
- 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. ...
随机推荐
- [源码解析] TensorFlow 分布式环境(4) --- WorkerCache
[源码解析] TensorFlow 分布式环境(4) --- WorkerCache 目录 [源码解析] TensorFlow 分布式环境(4) --- WorkerCache 1. WorkerCa ...
- python获取本地时间,时间戳与日期格式相互转换
附上代码与运行结果截图: import time # 获取当前时间 now = time.localtime() # 格式化日期 now_ = time.strftime('%Y-%m-%d %H:% ...
- [SPDK/NVMe存储技术分析]012 - 用户态ibv_post_send()源码分析
OFA定义了一组标准的Verbs,并提供了一个标准库libibvers.在用户态实现NVMe over RDMA的Host(i.e. Initiator)和Target, 少不了要跟OFA定义的Ver ...
- 22.2.14session和反反爬处理
22.2.14 session和反反爬处理 1.session: requests库包含session,都是用来对一个url发送请求,区别在于session是一连串的请求,在session请求过程中c ...
- leedcode算法
1.LeetCode - 合并两个链表 2. 3. 链表是否有环 https://jingyan.baidu.com/article/066074d69afb8d83c31cb068.ht ...
- Eureka和ZooKeeper都可以提供服务注册与发现的功能,请说说两个的区别?
1.ZooKeeper保证的是CP,Eureka保证的是AP ZooKeeper在选举期间注册服务瘫痪,虽然服务最终会恢复,但是选举期间不可用的 Eureka各个节点是平等关系,只要有一台Eureka ...
- 简述 synchronized 和 java.util.concurrent.locks.Lock 的异同?
Lock 是 Java 5 以后引入的新的 API,和关键字 synchronized 相比主要相同点: Lock 能完成 synchronized 所实现的所有功能:主要不同点:Lock 有比 sy ...
- springboot-数据访问之jdbc
官网的starthttps://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-starter 111 ...
- JavaScript 表单事件
表单事件,当用户与表单元素进行交互时发生. 实例: 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>表单事件& ...
- chubby 是什么,和 zookeeper 比你怎么看?
chubby 是 google 的,完全实现 paxos 算法,不开源.zookeeper 是 chubby的开源实现,使用 zab 协议,paxos 算法的变种.