可添加头尾的RecycleView的实现
界面编码设计实现中,我们肯定会用到列表展示控件,大家肯定用过ListView。后来google推出了RecycleView,帮我们去做了很多优化(内置viewholder增加复用率、可以支持局部刷新、布局可以通过外层指定layout等),正常的使用,如下:
MyRecycleViewAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_decorator);Component component = new ConCreateComponent();ComponentImplA impl1 = new ComponentImplA(component);impl1.operation();List<String> list = new ArrayList<>();for (int i = 0; i < 100; i++) {list.add("position " + i);}adapter = new MyRecycleViewAdapter(this);adapter.setData(list);}/*** 原始的yRecycleViewAdapter v1*/public void buttonv1(View view) {findViewById(R.id.recycleview).setVisibility(View.VISIBLE);findViewById(R.id.wrapperR).setVisibility(View.GONE);RecyclerView recyclerView = findViewById(R.id.recycleview);recyclerView.setLayoutManager(new LinearLayoutManager(this));recyclerView.setAdapter(adapter);}
但是RecycleView大家发现有一个问题,我们如果想要为这个RecycleView添加自定义的头部view、尾部view的话,官方这个明显做不到,那这时我们可以考虑用装饰者模式或者继承去扩展一下。
设计UML图
首先我们通过UML图,来设计一下,设计之前想一下,我们是想要扩展RecyclerView.Adapter和RecyclerView,从而可以实现addHeadView、addFootView的功能,那么需要以下几步骤。
1)首先,由于RecyclerView.Adapter已经是一个抽象类接口,我们自己继承与它,然后进行包装定义为WrapperRecyclerAdapter类
2)WrapperRecyclerAdapter肯定要持有RecyclerView.Adapter的引用,所以需要有一个构造方法,将RecyclerView.Adapter的引用传递进来
3)由于WrapperRecyclerAdapter继承与RecyclerView.Adapter,肯定要去实现关键的方法,onCreateViewHolder(创建viewitem的holder)、onBindViewHolder(viewholder数据绑定)、getItemCount(获取列表item的数量)
4)关键的一步来了,就是使用RecyclerView.Adapter、footviews、headviews,这三者组合,重写上面的三个重要方法,给列表相应位置创建对应的item
代码实现1
WrapperRecyclerAdapter
package com.itbird.design.decorator.recycleview;import android.view.View;
import android.view.ViewGroup;import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;import java.util.ArrayList;
import java.util.List;/*** RecyclerView.Adapter包装类,扩展实现headView、footView的添加* Created by itbird on 2022/6/10*/
public class WrapperRecyclerAdapter extends RecyclerView.Adapter {RecyclerView.Adapter adapter;List<View> headViews = new ArrayList<>();List<View> footViews = new ArrayList<>();public WrapperRecyclerAdapter(RecyclerView.Adapter adapter) {this.adapter = adapter;adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {@Overridepublic void onChanged() {notifyDataSetChanged();}});}@NonNull@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {//头部的,返回头部的viewholderif (position < headViews.size()) {return new WrapperViewHolder(headViews.get(position));}//adapter返回中间数据holderif (position >= headViews.size() && position < headViews.size() + adapter.getItemCount()) {return adapter.onCreateViewHolder(parent, adapter.getItemViewType(position - headViews.size()));}//尾部的,返回尾部的viewholderreturn new WrapperViewHolder(footViews.get(position - headViews.size() - adapter.getItemCount()));}@Overridepublic void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {if (position < headViews.size() || position >= adapter.getItemCount() + headViews.size()) {return;}//头部和底部不需要做处理,只需要真实的adapter需要处理adapter.onBindViewHolder(holder, position - headViews.size());}@Overridepublic int getItemViewType(int position) {return position;}@Overridepublic int getItemCount() {return headViews.size() + footViews.size() + adapter.getItemCount();}public void addHeadView(View view) {if (!headViews.contains(view)) {headViews.add(view);notifyDataSetChanged();}}public void addFootView(View view) {if (!footViews.contains(view)) {footViews.add(view);notifyDataSetChanged();}}public void removeHeadView(View view) {if (headViews.contains(view)) {headViews.add(view);notifyDataSetChanged();}}public void removeFootView(View view) {if (footViews.contains(view)) {footViews.remove(view);notifyDataSetChanged();}}static class WrapperViewHolder extends RecyclerView.ViewHolder {public WrapperViewHolder(@NonNull View itemView) {super(itemView);}}
}
这时再去调用,发现就可以如下调用
/*** 扩展的,可以增加头尾的recycleview v2*/public void buttonv2(View view) {findViewById(R.id.recycleview).setVisibility(View.VISIBLE);findViewById(R.id.wrapperR).setVisibility(View.GONE);RecyclerView recyclerView = findViewById(R.id.recycleview);recyclerView.setLayoutManager(new LinearLayoutManager(this));WrapperRecyclerAdapter wrapperRecyclerAdapter = new WrapperRecyclerAdapter(adapter);//这里head为什么不会全屏,因为LayoutInflater需要parent才会全屏wrapperRecyclerAdapter.addHeadView(LayoutInflater.from(this).inflate(R.layout.layout_header_view, recyclerView, false));wrapperRecyclerAdapter.addFootView(new Button(this));recyclerView.setAdapter(wrapperRecyclerAdapter);
// 面向对象的六大基本原则,好像不符合最小知道原则,每次调用需要去new WrapperRecyclerAdapter这样的一个包装者,这肯定是不对的,所以需要封装自己的recycleview}
看一下运行效果
代码实现2
这里我们发现一个问题,这样岂不是让开发者,每每次去使用的时候,new原始的adapter,还需要去new WrapperRecyclerAdapter,然后才能给recyclerView去setAdapter,面向对象的六大基本原则,好像不符合最小知道原则,每次调用需要去new WrapperRecyclerAdapter这样的一个包装者,这肯定是不对的,所以需要封装自己的recycleview。
所以我们做如下优化,将WrapperRecyclerAdapter的new操作,我们可以放入recyclerView中,这样外界开发者只需要去关心WrapperRecycleView和RecyclerView.Adapter就可以了,对于开发者来讲,只需关心RecyclerView自定义就可以了。
自定义WrapperRecycleView
,重写方法setAdapter,用于封装new WrapperRecyclerAdapter的操作
package com.itbird.design.decorator.recycleview;import android.content.Context;
import android.util.AttributeSet;
import android.view.View;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;/*** 自定义WrapperRecycleView,重写方法setAdapter,用于封装new WrapperRecyclerAdapter的操作* Created by itbird on 2022/6/10*/
public class WrapperRecycleView extends RecyclerView {WrapperRecyclerAdapter wrapperRecyclerAdapter;public WrapperRecycleView(@NonNull Context context) {super(context);}public WrapperRecycleView(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);}public WrapperRecycleView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overridepublic void setAdapter(@Nullable Adapter adapter) {wrapperRecyclerAdapter = new WrapperRecyclerAdapter(adapter);super.setAdapter(wrapperRecyclerAdapter);}@Nullable@Overridepublic Adapter getAdapter() {return wrapperRecyclerAdapter;}public void addHeadView(View view) {wrapperRecyclerAdapter.addHeadView(view);}public void addFootView(View view) {wrapperRecyclerAdapter.addFootView(view);}public void removeHeadView(View view) {wrapperRecyclerAdapter.removeHeadView(view);}public void removeFootView(View view) {wrapperRecyclerAdapter.removeFootView(view);}
}
调用一下
/*** 将wrapperadapter的new操作,内部实现 v3* 封装的必要性,这样的话,只需要关注WrapperRecycleView,不再需要关注WrapperRecyclerAdapter*/public void buttonv3(View view) {findViewById(R.id.wrapperR).setVisibility(View.VISIBLE);findViewById(R.id.recycleview).setVisibility(View.GONE);WrapperRecycleView wrapperRecycleView = findViewById(R.id.wrapperR);wrapperRecycleView.setLayoutManager(new LinearLayoutManager(this));wrapperRecycleView.setAdapter(adapter);wrapperRecycleView.addHeadView(LayoutInflater.from(this).inflate(R.layout.layout_header_view, wrapperRecycleView, false));wrapperRecycleView.addFootView(new Button(this));//这时再去考虑一个事情,我们通过装饰者模式把adapter封装了一层,如果adpater有数据更新,导致变动,这时会有问题吗?//这时会发现,并未更新,原因是装饰类,并未做事件响应}
是不是简单了很多。
可添加头尾的RecycleView的实现相关推荐
- 优雅的为RecyclerView添加头尾布局HeaderAndFooterWrapper
日常的开发中,我们需要为RecyclerView添加头尾布局,当我们已经写好了一个adapter,这时候如果要现在添加头尾布局,通常的做法是重写刚写完的adapter,再getItemViewType ...
- 初识 android v7 包
大家对于v4包都已经很熟悉了,现在在新建android项目时,v4包是默认导入的. v7包需要v4包的支持,在新建android项目时,v7包默认不导入,我们需要自己导入.主要对3.0以下版本提供Ac ...
- Leetcode-一篇帖子就够啦
# 注:下面按照算法类别由浅入深,把下面罗列的这些题刷完,并且多看这些题不同的解法(国际版mostvotes),看懂之后估计就不会有太大的问题啦~ 整体框架 数据结构: 一维:基础: 数组array( ...
- 【转】使用TCP协议连续传输大量数据时,是否会丢包,应如何避免?
[转]使用TCP协议连续传输大量数据时,是否会丢包,应如何避免? Posted on 2008-06-11 15:24 路缘 阅读(3868) 评论(0) 编辑 收藏 http://www.cnbl ...
- 2019-暑期实习生-自然语言处理算法岗-面试题
随着三月初蚂蚁金服内推开启,整个暑期实习生招聘大幕也正式打开,这一场从三月初持续到之后五月的笔试面试过程,确实让笔者真真切切的感受到基础的重要性,面试和笔试不仅从机器学习,自然语言处理,数据结构与算法 ...
- Android view.settran,Android RecyclerView从入门到玩坏
目录 前言 基础使用 分隔线 点击监听 搭配CardView 更丰富的条目 增删条目 快速添加视图 让RecyclerView支持复杂视图 最后前言 RecyclerView在Android界面开发当 ...
- Android Studio实现 历史上的今天
文章目录 一.项目概述 二.开发环境 三.主要实现 四.项目演示 五.项目总结 六.项目源码 一.项目概述 本项目名称叫做TodayHistory,顾名思义,就是"历史上的今天". ...
- 【PDF】java使用Itext生成pdf文档--详解
[API接口] 一.Itext简介 API地址:javadoc/index.html:如 D:/MyJAR/原JAR包/PDF/itext-5.5.3/itextpdf-5.5.3-javadoc/i ...
- Reporting报表开发知识汇总[个人原创]
[个人原创] ,转发请声明原文链接 了解 a) SSRS全称 SQL Server Reporting Services,是依赖于数据库运行的,是微软开发的重量级别的BI产品 b) ...
最新文章
- 归一化互相关Normalization cross correlation (NCC)
- css学习任务二:切图写代码
- 操作系统学习:系统调用与Linux0.12初始化详细流程
- table的td、th的一些样式问题(宽度,边框,滚动条)
- Retrofit 注解参数详解
- 游戏设计模式思考:“穿越火线”中的“策略模式”
- 如何正确处理 .NET 文件的 `File in use by another process` 异常 ?
- vuex webpack 配置_vue+webpack切换环境和打包之后服务器配置
- 计算机二级c语言考试真题及答案详解,计算机二级c语言试题及答案
- openwrt源码分析_编译个性化的OPENWRT固件(openWRT源码修改)
- 用python设计简易计算器代码_Python简易计算器制作方法代码详解
- PS:学习:一:删除图片不想要的部分
- ArcMap加载SHP文件
- 迷你游戏平台开发(二)
- JZOJ 4809. 挖金矿
- 2021-2027全球与中国Al2O3氧化铝陶瓷基板白板市场现状及未来发展趋势
- 【Errors】Errors during downloading metadata for repository ‘AppStream‘:
- ERP与MBA的关系
- java判断白天黑夜,获取Java中的所有夜晚时间
- 小程序与公众号共用服务器端,小程序和公众号能否共用同一个数据库
热门文章
- 在HTML中将垂直转换为平行,大物实验答案解析.doc
- VL53L0X 底层思路整理 (2)
- 【高速数字化仪应用案例系列】虹科Spectrum在天文领域的应用
- oracle goldengate学习笔记,【学习笔记】Oracle goldengate monitor使用笔记
- Oracle显示表裂开,【案例】Oracle RAC脑裂导致节点重启原因分析
- 从1G说到5G:科技改变生活
- Fanuc开发技术集-Focas2中英文函数对照表第五部分
- 协作型CRM软件能帮到你什么?
- 《区块链工程技术人员等职业信息》
- java vue 服务端渲染_vue服务端渲染缓存应用详解