介绍
在项目中有时会需要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头部固定相关推荐

  1. Android中当item数量超过一定大小RecyclerView高度固定

    Android中当item数量超过一定大小时,将RecyclerView高度固定 方法1 直接通过LayoutParams来设定相应高度 ViewGroup.LayoutParams lp = rv. ...

  2. android自定义起止时间的时间刻度尺,Android中自定义RecyclerView如何实现不固定刻度的刻度尺...

    Android中自定义RecyclerView如何实现不固定刻度的刻度尺 发布时间:2020-07-17 16:50:28 来源:亿速云 阅读:116 作者:小猪 这篇文章主要讲解了Android中自 ...

  3. Android 高级编程 RecyclerView 控件的使用

    RecyclerView 是Android 新添加的一个用来取代ListView的控件,它的灵活性与可替代性比listview更好. 看一下继承关系: ava.lang.Object    ↳ and ...

  4. Android Espresso(四)——RecyclerView

    文章目录 Android Espresso(四)--RecyclerView RecyclerViewActions API RecyclerView已定义API测试代码 RecyclerView自定 ...

  5. Android 控件 RecyclerView 看这篇就够了

    [Android 控件 RecyclerView] 概述 RecyclerView是什么 从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传 ...

  6. Android 控件 RecyclerView

    [Android 控件 RecyclerView] 概述 RecyclerView是什么 从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传 ...

  7. Android进阶:RecyclerView中DiffUtil的使用

    本文转载自:https://blog.csdn.net/zxt0601/article/details/52562770 一.概述 DiffUtil是support-v7:24.2.0中的新工具类,它 ...

  8. Android Studio开发RecyclerView遇到的各种问题以及解决(一)

    Android Studio开发RecyclerView遇到的各种问题以及解决(一) 参考文章: (1)Android Studio开发RecyclerView遇到的各种问题以及解决(一) (2)ht ...

  9. Android Studio新建类头部注释和添加函数注释模板及快捷键

    一,Android Studio新建类头部注释 是不是有时候看到这个很心烦 其实Studio中有设置修改这些注释模板的信息的功能 其实很简单,只需要两步: 1.打开Setting设置面板,找到File ...

  10. Android SrcollView嵌套recyclerView的使用

    今天,简单讲讲Android里使用SrcollView嵌套recyclerView需要注意的地方. 不废话了直接上代码,在使用时加上下面的代码就可以 recyclerView.setLayoutMan ...

最新文章

  1. java如何学习javaweb学习课程
  2. 用神经网络迭代次数曲线模拟原子光谱
  3. 数据中心怎么建更科学
  4. python3对urllib和urllib2进行了重构
  5. Autofac的AOP面向切面编程研究
  6. Java 中去除字符串中空格的方法
  7. 云原生应用 Kubernetes 监控与弹性实践
  8. 数据结构之队列的定义与简单实现
  9. JAVA线程池_并发队列工作笔记0004---Callable原理_多线程执行Callable任务
  10. 政务外网001---政务外网介绍
  11. Open3d之裁剪点云
  12. 动态规划算法经典例题_c动态规划精简例题
  13. Nginx配置共用80端口|端口转发端口映射
  14. 计算机d盘无法格式化,电脑的D盘无法进行格式化怎么办?最强悍的三种解决方式看这里!...
  15. stata15中文乱码_Stata14打开13数据乱码处理办法
  16. 使用Liquid实现简单的数据交换
  17. WinRAR安装教程
  18. 【Python】所有常用Python库和功能查询表
  19. C++ for_each函数
  20. MySQL 事务隔离级别

热门文章

  1. 2022届秋招笔试题小结:图
  2. 最小生成树:Kruskal算法
  3. go语言环境搭建及vim高亮设置
  4. 蔬菜大棚原理_温室大棚的原理是什么?
  5. 一致 先验分布 后验分布_分布式下的数据一致性问题
  6. 为什么录像总是很暗_为什么拍出的的照片总是很暗?看下是不是这2个原因造成的...
  7. 在HTML中添加图片阴影,html – 如何在CSS中为图像添加内部阴影[复制]
  8. wordpress如何整合html语言,怎么用wordpress建中英文双语及多语言切换的网站
  9. 厄拉多塞筛法求素数 c语言,求质数(Prime Number 素数)的方法——厄拉多塞筛法...
  10. 算法:258. Add Digits 各位相加