Android StickHeaderRecyclerView - 让recyclerview头部固定
介绍
在项目中有时会需要recyclerview滑动式时某个view滑出后会固定在头部显示,比较常用的比如手机联系人界面、地区选择界面等。 StickHeaderRecyclerView就是实现这个功能的。效果图:
这样的控件网上一抓一大把了,本控件的优点就是使用简单- lib简单 - 使用的语法也简单(之前下了2个类似开源项目,都是上万行代码。读起来麻烦、改起来麻烦就自己写了这个控件)
使用
只需要让你的adapter实现StickHeaderDecoration.StickHeaderInterface接口,方法boolean isStick(int position)中返回的值就标识当前位置的view是否需要固定。
同时需要让Adapter中的item不复用(如果怕影响性能也可以单独让需要固定的view不复用) 在adapter构造方法中setHasStableIds(true); 同时复写adapter的public long getItemId(int position) {return position;}
上代码
public class NormalAdapter extends RecyclerView.Adapter<NormalAdapter.InnerHolder> implements StickHeaderDecoration.StickHeaderInterface{NormalAdapter(Activity activity, List<String> dates){this.activity = activity;this.dates = dates;}@Overridepublic boolean isStick(int position) {return position % 6 == 0;}Activity activity;private List<String> dates;@Overridepublic InnerHolder onCreateViewHolder(ViewGroup parent, int viewType) {View inflate = LayoutInflater.from(activity).inflate(R.layout.item, parent,false);return new InnerHolder(inflate);}@Overridepublic void onBindViewHolder(InnerHolder holder, int position) {if(isStick(position)){holder.itemView.setBackgroundResource(R.color.colorAccent);holder.tvText.setText(position / 6 +"");}else{holder.itemView.setBackgroundResource(R.color.white);holder.tvText.setText(dates.get(position));}}@Overridepublic int getItemCount() {return dates.size();}class InnerHolder extends RecyclerView.ViewHolder{TextView tvText;public InnerHolder(View itemView) {super(itemView);tvText = (TextView) itemView.findViewById(R.id.tvText);}} }
activity代码
public class MainActivity extends Activity {private RecyclerView recycle;private List<String> dates = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recycle = (RecyclerView) findViewById(R.id.recycle);for(int i=0;i<66;i++){dates.add("date : "+i);}recycle.setLayoutManager(new LinearLayoutManager(this));recycle.setAdapter(new NormalAdapter(this, dates));recycle.addItemDecoration(new StickHeaderDecoration(recycle));}}
完成了
原理
先上核心类代码
public class StickHeaderDecoration extends RecyclerView.ItemDecoration {public interface StickHeaderInterface {/*** is this item need stick* @param position now item position in the recyclerView* @return true : need stick else not*/boolean isStick(int position);}private RecyclerView recyclerView;private RecyclerView.LayoutManager manager;private RecyclerView.Adapter adapter;private StickHeaderInterface stickHeaderInterface;/*** 进行一些容错检查*/public StickHeaderDecoration(RecyclerView recyclerView) {this.recyclerView = recyclerView;this.manager = recyclerView.getLayoutManager();this.adapter = recyclerView.getAdapter();if (adapter == null) {throw new RuntimeException("please set Decoration after set adapter");}if (adapter instanceof StickHeaderInterface) {stickHeaderInterface = (StickHeaderInterface) adapter;return;}throw new RuntimeException("please make your adapter implements StickHeaderInterface");}/*** 绘制头部的stick view*/@Overridepublic void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {super.onDrawOver(c, parent, state);View childAt = parent.getChildAt(0);if (childAt == null)return;RecyclerView.ViewHolder childViewHolder = parent.getChildViewHolder(childAt);int position = childViewHolder.getPosition();for (int i = position; i >= 0; i--) {if (stickHeaderInterface.isStick(i)) {int top = 0;if (position + 1 < adapter.getItemCount()) {if (stickHeaderInterface.isStick(position + 1)) {View childNext = parent.getChildAt(1);top = manager.getDecoratedTop(childNext) < 0 ? 0 : manager.getDecoratedTop(childNext);}}RecyclerView.ViewHolder inflate = recyclerView.getAdapter().createViewHolder(parent,recyclerView.getAdapter().getItemViewType(i));recyclerView.getAdapter().bindViewHolder(inflate, i);int measureHeight = getMeasureHeight(inflate.itemView);c.save();if (top < inflate.itemView.getMeasuredHeight() && top > 0) {c.translate(0, top - measureHeight);}inflate.itemView.draw(c);c.restore();return;}}}/*** 测量控件的高度** @param header*/private int getMeasureHeight(View header) {int widthSpec = View.MeasureSpec.makeMeasureSpec(recyclerView.getWidth(), View.MeasureSpec.EXACTLY);int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);header.measure(widthSpec, heightSpec);header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight());return header.getMeasuredHeight();} }
首先ItemDecoration是一个接口,通过RecyclerView的 recycle.addItemDecoration方法设置进去
其中只有6个方法其中3个过时了。我们这儿只需要对onDrawOver进行操作。
onDrawOver是当前RecyclerView绘制完毕后调用,可以其中进行绘制。我们的头部固定其实就是在这个方法中绘制进去的。
算法
1.这儿我们需要判断当前显示item的前面是否有需要固定的item(这儿取名为beforitem)如果有则绘制在顶部
2.我们还需要当第二个固定的item把前面的item慢慢顶上去的效果,这儿通过判断当前显示的第一个item的下一个item是否需要固定,如果需要则通过manager.getDecoratedTop(childNext)获取这个item距离顶部的距离然后通过计算把beforitem先上移动一定的距离。
基本原理就这样,相信代码更加有说服力,github 地址
https://github.com/LiuLinXin/StickHeaderRecyclerView-philer
待优化
头部view现在是通过ondraw绘制进去的,不能相应点击事件等。暂时没相处好的解决办法,希望有想法的朋友提示下。
转载于:https://www.cnblogs.com/zhujiabin/p/9804079.html
Android StickHeaderRecyclerView - 让recyclerview头部固定相关推荐
- Android中当item数量超过一定大小RecyclerView高度固定
Android中当item数量超过一定大小时,将RecyclerView高度固定 方法1 直接通过LayoutParams来设定相应高度 ViewGroup.LayoutParams lp = rv. ...
- android自定义起止时间的时间刻度尺,Android中自定义RecyclerView如何实现不固定刻度的刻度尺...
Android中自定义RecyclerView如何实现不固定刻度的刻度尺 发布时间:2020-07-17 16:50:28 来源:亿速云 阅读:116 作者:小猪 这篇文章主要讲解了Android中自 ...
- Android 高级编程 RecyclerView 控件的使用
RecyclerView 是Android 新添加的一个用来取代ListView的控件,它的灵活性与可替代性比listview更好. 看一下继承关系: ava.lang.Object ↳ and ...
- Android Espresso(四)——RecyclerView
文章目录 Android Espresso(四)--RecyclerView RecyclerViewActions API RecyclerView已定义API测试代码 RecyclerView自定 ...
- Android 控件 RecyclerView 看这篇就够了
[Android 控件 RecyclerView] 概述 RecyclerView是什么 从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传 ...
- Android 控件 RecyclerView
[Android 控件 RecyclerView] 概述 RecyclerView是什么 从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传 ...
- Android进阶:RecyclerView中DiffUtil的使用
本文转载自:https://blog.csdn.net/zxt0601/article/details/52562770 一.概述 DiffUtil是support-v7:24.2.0中的新工具类,它 ...
- Android Studio开发RecyclerView遇到的各种问题以及解决(一)
Android Studio开发RecyclerView遇到的各种问题以及解决(一) 参考文章: (1)Android Studio开发RecyclerView遇到的各种问题以及解决(一) (2)ht ...
- Android Studio新建类头部注释和添加函数注释模板及快捷键
一,Android Studio新建类头部注释 是不是有时候看到这个很心烦 其实Studio中有设置修改这些注释模板的信息的功能 其实很简单,只需要两步: 1.打开Setting设置面板,找到File ...
- Android SrcollView嵌套recyclerView的使用
今天,简单讲讲Android里使用SrcollView嵌套recyclerView需要注意的地方. 不废话了直接上代码,在使用时加上下面的代码就可以 recyclerView.setLayoutMan ...
最新文章
- java如何学习javaweb学习课程
- 用神经网络迭代次数曲线模拟原子光谱
- 数据中心怎么建更科学
- python3对urllib和urllib2进行了重构
- Autofac的AOP面向切面编程研究
- Java 中去除字符串中空格的方法
- 云原生应用 Kubernetes 监控与弹性实践
- 数据结构之队列的定义与简单实现
- JAVA线程池_并发队列工作笔记0004---Callable原理_多线程执行Callable任务
- 政务外网001---政务外网介绍
- Open3d之裁剪点云
- 动态规划算法经典例题_c动态规划精简例题
- Nginx配置共用80端口|端口转发端口映射
- 计算机d盘无法格式化,电脑的D盘无法进行格式化怎么办?最强悍的三种解决方式看这里!...
- stata15中文乱码_Stata14打开13数据乱码处理办法
- 使用Liquid实现简单的数据交换
- WinRAR安装教程
- 【Python】所有常用Python库和功能查询表
- C++ for_each函数
- MySQL 事务隔离级别
热门文章
- 2022届秋招笔试题小结:图
- 最小生成树:Kruskal算法
- go语言环境搭建及vim高亮设置
- 蔬菜大棚原理_温室大棚的原理是什么?
- 一致 先验分布 后验分布_分布式下的数据一致性问题
- 为什么录像总是很暗_为什么拍出的的照片总是很暗?看下是不是这2个原因造成的...
- 在HTML中添加图片阴影,html – 如何在CSS中为图像添加内部阴影[复制]
- wordpress如何整合html语言,怎么用wordpress建中英文双语及多语言切换的网站
- 厄拉多塞筛法求素数 c语言,求质数(Prime Number 素数)的方法——厄拉多塞筛法...
- 算法:258. Add Digits 各位相加