搭配BRVAH高效使用RecyclerView
学习目标
熟悉使用 BRVAH 解决对应各种 adapter 需求
概述
BRVAH 是 Github 上的一个很棒的开源项目,主要作用是帮助我们更加高效的使用 Recyclerview 控件,处理项目中常见需求的 Adapter,使用起来非常方便,更多介绍可去BRVAH官网查看。
BRVAH 主要是针对 Adapter 来设计的。
BRVAH 为我们提供了一般情况下的BaseQuickAdapter
,和几个特定需求下的Adapter,BaseMultiItemQuickAdapter
用于复杂类布局列表;BaseItemDraggableAdapter
用于拖拽移动和滑动删除类列表; BaseSectionQuickAdapter
用于带 Section 头部 View 的列表。
build.gradle 配置说明
添加资源库
allprojects {repositories {...maven { url "https://jitpack.io" }}
}
添加依赖
dependencies {compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:VERSION_CODE'
}
VERSION_CODE
的最新版本可以参考这里。
功能概要说明
1. 实现Recyclerview的列表加载动画效果
我们只需将自建的 xxAdapter 继承 BRVAH 对应满足需求的 Adapter,然后在 Activity 中实例化,通过openLoadAnimation()
方法完成特定的动画效果。
BRVAH 支持 5 种动画,BaseQuickAdapter.ALPHAIN
淡入、BaseQuickAdapter.SLIDEIN_BOTTOM
从底部入、BaseQuickAdapter.SLIDEIN_LEFT
从左边进入、BaseQuickAdapter.SLIDEIN_RIGHT
从右边进入和自定义动画。
关于自定义的动画,可以通过实现 BaseAnimation
这个类,重写
getAnimators(View view)
方法来完成自定义动画。
2. 实现Recyclerview的复杂布局列表
在实际应用中经常会遇到各种样式的列表、宫格和列表同时存在、分类列表等情况。
2.1 Recyclerview 多样式 item 排列的效果
对于多样式的列表,根据需求创建 type 实体类实现 MultiItemEntity。 xxAdapter继承 BaseMultiItemQuickAdapter
类,在构造方法中调用addItemType ()
方法加入定义的 itemType 和对应布局,在 Activity 中实例化即可。
2.2 Recyclerview 宫格和列表的混排样式
关于 Grid 和 List 的混排样式,Grid 样式是一行有多个,而 List 样式是一行只有一个。我们可以把 List 样式看成是 Grid 样式,它就相当于把一个 Grid 的 item 拉长了的样子。
列表与网格混排的布局效果,我们可以创建 xxAdapter 继承 BaseMultiItemQuickAdapter
添加对应 item 类型的布局文件,在 Activity 中创建 GridLayoutManager
对象,设置 spanSize
属性,通过 Adapter 的 setSpanSizeLookup
方法设置每种 item 类型对应的 spanSize。设置 Recyclerview 的 addItemDecoration()
方法设置添加分割线或设置 item 间距。
代码片段:
...
gridLayoutManager = new GridLayoutManager(this,3);mRecyclerView.setLayoutManager(gridLayoutManager);mAdapter = new GridManagerAdapter(getDataType());// 设置横跨度// 1:就是横跨1/3// 2:就是横跨2/3// 3:就是横跨一整行mAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() {@Overridepublic int getSpanSize(GridLayoutManager gridLayoutManager, int position) {return getDataType().get(position).getSpanSize();}});mRecyclerView.setAdapter(mAdapter);mRecyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {@Overridepublic void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {super.getItemOffsets(outRect, view, parent, state);GridLayoutManager.LayoutParams layoutParams = (GridLayoutManager.LayoutParams)view.getLayoutParams();int spanSize = layoutParams.getSpanSize();int spanIndex = layoutParams.getSpanIndex();// 从左到右 0~if (spanSize == gridLayoutManager.getSpanCount()) {outRect.top = 20;}}});// 假设数据private List<MultipleItem> getDataType() {int type = 0;for (int i = 0;i < 13;i++) {if (i < 9) {type = 1;} else {type = 2;}types.add(i,type);}List<MultipleItem> list = new ArrayList<>();for (int j = 0;j < types.size();j++) {if (types.get(j) == 1) {list.add(new MultipleItem(1,1));} else if (types.get(j) == 2) {list.add(new MultipleItem(2,3));}}return list;}
...
在创建 GridLayoutManager
对象时,有一个 spanSize
的参数需要设置,它的作用就是使原来一个 item 占满一行变为可以最多三个 item 占满一行。
而设置 setSpanSizeLookup()
方法返回的是对应每种 item 类型返回具体的横跨大小。比如上面代码中 TYPE_GRID
类型的 item 在设置的 spanSize 是 1,而 GridLayoutManager 设置的 spanSize 是 3,那么该类型的 item 就会以 3 个 item 占满一行,相当于每个 item 占一行的 1/3。
在我们使用 addItemDecoration()
添加分割线的方法中对这种混排的列表设置 item 间距的时候,在 getItemOffsets()
方法里,通过 GridLayoutManager.LayoutParams
获取 spanSize 来确定 item 类型设置对应间距,其中 spanIndex
表示当前行 item 对应的下标位置,从左到右依次从 0 开始。
2.3 Recyclerview 嵌套 Recyclerview 的复杂布局
简单的分析下上图的界面布局样式,最外面一个RecyclerView,它里面的每个 item 的布局样式,最上面用 Banner 轮播图控件,下面是各种样式 item 列表的形式,其中有一个可左右滑动的 item,它是嵌套的一个 RecyclerView。
使用 BaseMultiItemQuickAdapter
在重写的 convert()
方法中实例化子 Recyclerview,同样的步骤在进行子 Recyclerview 设置,需要注意的是Recyclerview 嵌套 Recyclerview 会出现子 Recyclerview 抢焦点的问题,导致界面顶部部分控件被挤出,只需在最外面的 Recyclerview 的包裹容器中设置属性 android:descendantFocusability="blocksDescendants"
即可。通过 BRVAH 的 addHeaderView()
方法设置头部布局。
代码片段:
@Overrideprotected void convert(BaseViewHolder helper, MultiItemEntity item) {switch (helper.getItemViewType()) {...case MultipleItem.DOUBANTIME:RecyclerView recyclerView = helper.getView(R.id.recyclerview_item_view);recyclerView.setLayoutManager(new LinearLayoutManager(mContext,LinearLayoutManager.HORIZONTAL,false));recyclerView.setHasFixedSize(true);recyclerView.setAdapter(new RrecyclerViewAdapter(DataServer.getReItemData()));break;}}
2. 实现Recyclerview拖拽滑动删除
添加 RecyclerView 的拖拽和滑动移除很简单,只需 xxAdapter 继承 BaseItemDraggableAdapter
类,在 Activity 中,添加 OnItemDragListener
和 OnItemSwipeListener
两个接口,通过 xxAdapter 配置基本属性即可。
代码片段:
OnItemDragListener listener = new OnItemDragListener() {@Overridepublic void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos) {// item 拖拽的起始位置Log.d(TAG,"drag start");}@Overridepublic void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) {// item 拖拽的过程位置变化Log.d(TAG, "move from: " + source.getAdapterPosition() + " to: " + target.getAdapterPosition());}@Overridepublic void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) {// item 拖拽的终点位置Log.d(TAG, "drag end");}};OnItemSwipeListener onItemSwipeListener = new OnItemSwipeListener() {@Overridepublic void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) {// item 滑动的起始位置Log.d(TAG, "view swiped start: " + pos);}@Overridepublic void clearView(RecyclerView.ViewHolder viewHolder, int pos) {// item 滑动后的恢复位置Log.d(TAG, "View reset: " + pos);}@Overridepublic void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos) {// item 滑动的移除位置Log.d(TAG, "View Swiped: " + pos);}@Overridepublic void onItemSwipeMoving(Canvas canvas, RecyclerView.ViewHolder viewHolder,float dX, float dY, boolean isCurrentlyActive) {// item 滑动的过程canvas.drawColor(ContextCompat.getColor(ItemDragAndSwipUseActivity.this,R.color.colorKbtt));}};
ItemDragAndSwipeCallback itemDragAndSwipeCallback = new ItemDragAndSwipeCallback(mAdapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemDragAndSwipeCallback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);mItemDragAndSwipeCallback.setSwipeMoveFlags(ItemTouchHelper.START | ItemTouchHelper.END);// open slide to deletemAdapter.enableSwipeItem();mAdapter.setOnItemSwipeListener(onItemSwipeListener);// open dragmAdapter.enableDragItem(itemTouchHelper);mAdapter.setOnItemDragListener(listener);mRecyclerView.setAdapter(mAdapter);
3. 实现Recyclerview监听事件
BRVAH为我们提供好了全面的 item 和 item 子 View 的监听事件,我们只需在继承 BRVAH 提供的 Adapter 的基础上,通过 xxAdapter 来调用对应的监听,只是设置监听子 View 前,我们需要在 xxAadapter 中对应的 item 的子 View 注册对应的监听事件。
3.1 对于 item 的监听事件处理
直接在 Activity 中添加
item 点击事件
adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {@Overridepublic void onItemClick(BaseQuickAdapter adapter, View view, int position) {Log.d(TAG, "onItemClick: ");Toast.makeText(ItemClickActivity.this, "onItemClick" + position, Toast.LENGTH_SHORT).show();}});
item 长按监听事件
adapter.setOnItemLongClickListener(new BaseQuickAdapter.OnItemLongClickListener() {@Overridepublic boolean onItemLongClick(BaseQuickAdapter adapter, View view, int position) {Log.d(TAG, "onItemLongClick: ");Toast.makeText(ItemClickActivity.this, "onItemLongClick" + position, Toast.LENGTH_SHORT).show();return false;}});
3.2 对 item 中子 View 的监听事件处理
首先需要在 xxAdapter 中注册子 View 的监听事件。
点击监听事件
@Overrideprotected void convert(BaseViewHolder viewHolder, Status item) {viewHolder.setText(R.id.tweetName, item.getUserName()).setText(R.id.tweetText, item.getText()).setText(R.id.tweetDate, item.getCreatedAt()).setVisible(R.id.tweetRT, item.isRetweet()).addOnClickListener(R.id.tweetAvatar).addOnClickListener(R.id.tweetName).linkify(R.id.tweetText);}
长按监听事件
@Overrideprotected void convert(BaseViewHolder helper, Status item) {helper.setText(R.id.tweetName, item.getUserName()).setText(R.id.tweetText, item.getText()).setText(R.id.tweetDate, item.getCreatedAt()).setVisible(R.id.tweetRT, item.isRetweet()).addOnLongClickListener(R.id.tweetText).linkify(R.id.tweetText);}
然后在 Activity 中设置对应的子 View 监听事件
点击事件
adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {@Overridepublic boolean onItemChildClick(BaseQuickAdapter adapter, View view, int position) {Log.d(TAG, "onItemChildClick: ");Toast.makeText(ItemClickActivity.this, "onItemChildClick" + position, Toast.LENGTH_SHORT).show();return false;}});
子 View 长按事件
adapter.setOnItemChildLongClickListener(new BaseQuickAdapter.OnItemChildLongClickListener() {@Overridepublic void onItemChildLongClick(BaseQuickAdapter adapter, View view, int position) {Log.d(TAG, "onItemChildLongClick: ");Toast.makeText(ItemClickActivity.this, "onItemChildLongClick" + position, Toast.LENGTH_SHORT).show();}});
4. 实现Recyclerview 刷新
列表下拉刷新和上拉加载是最常用的,BRVAH 虽然也提供了刷新功能,但只是上拉加载更多,而且样式也是固定的,实现下拉刷新还得用 SwipeRefreshLayout 来完成,这也容易理解,因为 BRVAH 主要是对 Adapter 的服务,所以这里只是简单说下 BRVAH 有关上拉加载更多的使用。
在按照 BRVAH 设置完 xxAdapter 后,在 Activity 中,让类实现 BaseQuickAdapter.RequestLoadMoreListener
接口,会重写 onLoadMoreRequested()
方法,在方法中调用 mAdapter.addData()
来添加新的数据,接着设置 mAdapter.loadMoreComplete()
,在数据都加载完后设置 mAdapter.loadMoreEnd(false)
显示数据加载完毕。
@Overridepublic void onLoadMoreRequested() {mSwipeRefreshLayout.setEnabled(false);if (loadCount < 2) {final List<MultipleItem> data = DataServer.getRefreshItemData(getServerData());mAdapter.addData(data);mAdapter.loadMoreComplete();loadCount+=1;} else {mAdapter.loadMoreEnd(false); // 显示加载完毕}// 设置下拉刷新实效mSwipeRefreshLayout.setEnabled(true);}
还有就是在下拉刷新的时候,使上拉加载更多失效。
mAdapter.setEnableLoadMore(true);
5. 实现Recyclerview 添加 Section 头部 View
设置 MySection 类继承 SectionEntity
,创建不同的构造方法来设置 item 是否有 header。在 adapter 中,增加了 convertHead()
方法来加载 head 数据。在 Activity 中根据数据创建不同的 MySection 对象加入集合,设置给 adapter。
public class MySection extends SectionEntity<String>{private boolean isMore;public MySection(boolean isHeader, String header,boolean isMore) {super(isHeader, header);this.isMore = isMore;}public MySection(String s) {super(s);}public void setMore(boolean more) {isMore = more;}
}
在 adapter 中,构造方法需要传入两个不同的布局 id,第一个是 item 的 layout id,第二个是 head,item 的数据加载在 convert()
方法中,head 的数据加载在 convertHead()
方法中。
public class SectionAdpater extends BaseSectionQuickAdapter<MySection,BaseViewHolder> {public SectionAdpater(int layoutResId, int sectionHeadResId, List<MySection> data) {super(layoutResId, sectionHeadResId, data);}// 加载 head 数据@Overrideprotected void convertHead(BaseViewHolder helper, MySection item) {helper.setText(R.id.title_tv,item.header);helper.addOnClickListener(R.id.more_btn);}// 加载 item 数据@Overrideprotected void convert(BaseViewHolder helper, MySection item) {}
}
在 Activity 中
...
// 部分代码
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);mRecyclerView.setLayoutManager(new GridLayoutManager(this,3));mData = getData(3);
SectionAdpater sectionAdpater = new SectionAdpater(R.layout.item_section_content,R.layout.def_section_head, mData);...// 假数据private List<MySection> getData(int size) {ArrayList<MySection> data = new ArrayList<>(size);data.add(new MySection(true,"1",true));for (int i =0;i < size;i++) {data.add(new MySection("haha"));}data.add(new MySection(true,"2",true));for (int i =0;i < size;i++) {data.add(new MySection("haha"));}data.add(new MySection(true,"3",true));for (int i =0;i < size;i++) {data.add(new MySection("haha"));}return data;}
根据数据确定不同的样式,用不同的构造方法设置 item 布局。
重要参考:BRVAH
搭配BRVAH高效使用RecyclerView相关推荐
- BRVAH(让RecyclerView变得更高效) (3)
本文来自网易云社区 作者:吴思博 3 实现列表加载动画效果 3.1默认动画 我们只需将自建的 adapter 继承它对应满足需求的 Adapter,然后在 Activity 中实例化,通过ope ...
- 挑战练习10.6 实现高效的RecyclerView刷新
把原本使用的Adapter的notifyDataSetChanged方法换成定位刷新RecyclerView.Adapter的notifyItem. 1.在CrimeListFragment里面定义一 ...
- [Android] DiffUtil在RecyclerView中的使用详解
概述 DiffUtil是recyclerview support library v7 24.2.0版本中新增的类,根据Google官方文档的介绍,DiffUtil的作用是比较两个数据列表并能计算出一 ...
- (01)recyclerview的基本使用
1.几个重要的类 1.1 简述:首先说明他的几个重要的类 1.1.2 RecyclerView.Adapter 抽象类,为RecyclerView提供数据,一般根据不同的业务需求来编写具体的实现类. ...
- 一个适用于ListView/GridView/RecyclerView的通用适配器
简化大量重复代码 支持多布局 自定义图片加载 常用数据操作 view复用 RecyclerView item 点击和长按事件 GitHub源码地址 简书地址 gradle依赖 dependencies ...
- LinkedBlockingQueue源码解析(1)
此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1.对于LinkedBlockingQueue需要掌握以下几点 创建 入队(添加元素) 出队(删除元素) 2 ...
- 网易有数的“正确”使用方式——洞察数据中隐藏的故事
此文已由作者王文开授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 网易有数提供了用户非常灵活的图表制作能力,其设计原理是希望用户能够通过"搭积木"的形式, ...
- 知物由学 | 如何从勒索软件的攻击中全身而退
欢迎访问网易云社区,了解更多网易技术产品运营经验. "知物由学"是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理 ...
- 微服务化的不同阶段 Kubernetes 的不同玩法
欢迎访问网易云社区,了解更多网易技术产品运营经验. 作为容器集群管理技术竞争的大赢家,Kubernetes已经和微服务紧密联系,采用Kubernetes的企业往往都开始了微服务架构的探索.然而不同企业 ...
最新文章
- 【Flutter】Flutter 混合开发 ( 简介 | Flutter 混合开发集成步骤 | 创建 Flutter Module )
- 【Android 应用开发】Activity 返回堆栈清除操作 ( 默认状态 | 清除返回堆栈配置 | 不清除返回堆栈配置 | 清除指定界面配置 )
- 网络管理员&MCSE2003之12: 第8章 应用管理模板和审核策略
- 前端一HTML:二十四伪类
- rbac 权限分配, 基于formset实现,批量增加
- 真正的代码宝库:Google Code Search
- 学校为什么要单位接收函_为什么要选择语言学校留学?
- Windows XP图片查看器打不开图片的解决办法
- 基于web的客栈、公寓、民宿管理平台的设计与实现
- 作为管理者,就不要总等着领导给你布置任务了
- 云服务器部署论坛系统discuz,腾讯云服务器利用镜像搭建Discuz!论坛完整教程
- 多个约束的lagrange multiplier证明.
- OSChina 娱乐弹弹弹——程序猿的酒文化
- 2分钟部署人生模拟器,解锁人生新剧情
- QT之QTableWidget控件
- 网站是用什么来赚钱的?
- 2019年架构软考论文押题(二)
- 斐波那契生兔子问题(一月大兔子生a对,二月大兔子生b对,三月大兔子生c对。。。)
- Java会被禁吗_关于java:如果字符串对象被禁闭,那么为什么一个更改不会影响其他对象...
- 【PAT】06 图论