Android RecyclerView实现吸顶动态效果,附详细效果图 您所在的位置:网站首页 淘宝自定义页图片 Android RecyclerView实现吸顶动态效果,附详细效果图

Android RecyclerView实现吸顶动态效果,附详细效果图

#Android RecyclerView实现吸顶动态效果,附详细效果图| 来源: 网络整理| 查看: 265

文章目录 一、ItemDecoration二、实现RecyclerView吸顶效果1、实现一个简单的RecyclerView2、通过ItemDecoration画分割线3、画出每个分组的组名4、实现吸顶效果 完整demo

链接:https://download.csdn.net/download/JasonXu94/87786702 202212220944467

一、ItemDecoration

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yinKVw8W-1684338638199)(null)]ItemDecoration 允许应用给具体的 View 添加具体的图画或者 layout 的偏移,对于绘制 View之间的分割线,视觉分组边界等等是非常有用的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9tV6bsdW-1684338638181)(null)]当我们调用 addItemDecoration() 方法添加 decoration 的时候,RecyclerView 就会调用该类的 onDraw 方法去绘制分割线,也就是说:分割线是绘制出来的。

RecyclerView.addItemDecoration()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QbCX4qeB-1684338638228)(null)]RecyclerView.ItemDecoration,该类为抽象类,官方目前只提供了一个实现类 DividerItemDecoration。

public abstract static class ItemDecoration

public class DividerItemDecoration extends RecyclerView.ItemDecoration

里面有3个方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PF6v7Oky-1684338638211)(null)]onDraw(): 在提供给RecyclerView的画布上绘制任何适当的装饰。通过此方法绘制的任何内容都将在绘制项目视图之前被绘制,因此将出现在视图的下方。

public void onDraw(Canvas c, RecyclerView parent, State state) { onDraw(c, parent); }

绘制效果

image-20230516164805173

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oI7eqZd6-1684338638249)(null)]onDrawOver():在提供给RecyclerView的画布上绘制任何适当的装饰。通过这种方法绘制的任何内容都将在项目视图被绘制之后被绘制,因此将出现在视图上方。

public void onDrawOver(Canvas c, RecyclerView parent, State state) { onDrawOver(c, parent); }

绘制效果

image-20230516164822315

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sDcBvRbp-1684338638239)(null)]getItemOffsets():检索给定项的任何偏移量。outRect的每个字段指定项目视图应该插入的像素数,类似于padding或margin。默认实现将outRect的界限设置为0,并返回。

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) { getItemOffsets(outRect, ((LayoutParams)view.getLayoutParams()).getViewLayoutPosition(), parent); } 二、实现RecyclerView吸顶效果 1、实现一个简单的RecyclerView

下面这个RecyclerView的实现细节略。

image-20230516164844439

2、通过ItemDecoration画分割线

自定义ItemDecoration。

创建 fruitDecotion 类 继承 ItemDecoration,并实现onDraw、onDrawover、getItemOffsets三个方法。

RecyclerView调用自定义的fruitDecoration

RecyclerView.addItemDecoration(new fruitDecoration(this))

在getItemOffsets画分割线,当是组名时,预留更大的空间(即分割线的height比普通分割线大)。

@Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); if (parent.getAdapter() instanceof fruitAdapter){ // parent.getAdapter()获取到当前RecyclerView的Adapter fruitAdapter adapter = (fruitAdapter) parent.getAdapter(); // 获取当前view的位置 int position = parent.getChildLayoutPosition(view); if (adapter.isGroupHeader(position)) { // 如果是头部,则预留更大的地方 outRect.set(0, groupHeaderHeight, 0, 0); }else { outRect.set(0, 4, 0, 0); } }

实现效果

2022122209445211

3、画出每个分组的组名

当是组名时,在较大分割线哪里画出组名。在onDraw()方法里实现

@Override public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.onDraw(c, parent, state); if (parent.getAdapter() instanceof fruitAdapter) { fruitAdapter adapter = (fruitAdapter) parent.getAdapter(); //当前屏幕中item的个数 int count = parent.getChildCount(); // 获取当前RecyclerView距离屏幕左边的padding int left = parent.getPaddingLeft(); // right == RecyclerView的宽度 - RecyclerView的右padding int right = parent.getWidth() - parent.getPaddingRight(); for (int i = 0; i < count; i++) { //获取对应 i 的 view View view = parent.getChildAt(i); // 获取 i 的 view 的布局位置 int position = parent.getChildLayoutPosition(view); // 判断是否是头部 boolean isGroupHeader = adapter.isGroupHeader(position); // i 的 view 是头部并且 当前view的top位置距离屏幕的顶部还有距离 if(isGroupHeader && view.getTop() - groupHeaderHeight - parent.getPaddingTop() >=0) { c.drawRect(left, view.getTop() - groupHeaderHeight, right, view.getTop(), headPaint); String groupName = adapter.getGroupName(position); textPaint.getTextBounds(groupName, 0, groupName.length(), textRect); c.drawText(groupName, left + 20, view.getTop() - groupHeaderHeight / 2f + textRect.height() / 2f, textPaint); }else if(view.getTop() - groupHeaderHeight - parent.getPaddingTop() >=0){ //分割线 c.drawRect(left, view.getTop() - 4, right, view.getTop(), headPaint); } } } }

实现效果

image-20230516164935046

4、实现吸顶效果

因为onDrawOver方法是在itemView画了之后才画,所以组名的吸顶是写在onDrawOver方法里。需要注意的时,当我们的第二个组名到顶部的时候,要把当前顶部的组名给替换掉。

@Override public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.onDrawOver(c, parent, state); if (parent.getAdapter() instanceof fruitAdapter) { fruitAdapter adapter = (fruitAdapter) parent.getAdapter(); //TODO 返回可见区域内的第一个item的position int position =((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition(); // 获取第一个item的view View itemView = parent.findViewHolderForAdapterPosition(position).itemView; int left = parent.getPaddingLeft(); int right = parent.getWidth() - parent.getPaddingRight(); int top = parent.getPaddingTop(); //TODO 当第二个是头部时, boolean isGroupHeader = adapter.isGroupHeader(position + 1); if (isGroupHeader) { int bottom = Math.min(groupHeaderHeight, itemView.getBottom() - parent.getPaddingTop()); c.drawRect(left, top, right, top + bottom, headPaint); String groupName = adapter.getGroupName(position); textPaint.getTextBounds(groupName, 0, groupName.length(), textRect); c.drawText(groupName, left + 20, top + bottom - groupHeaderHeight / 2f + textRect.height() / 2f, textPaint); }else { // 如果不是头部, 即普通的itemView,则当前的头部一直固定在顶部 c.drawRect(left, top, right, top + groupHeaderHeight, headPaint);; String groupName = adapter.getGroupName(position); textPaint.getTextBounds(groupName, 0, groupName.length(), textRect); c.drawText(groupName, left + 20, top + groupHeaderHeight / 2f + textRect.height() / 2f, textPaint); } } }

实现效果

image-20230516164951564

完整demo

链接:https://download.csdn.net/download/JasonXu94/87786702

到此这篇关于Android RecyclerView实现吸顶动态效果流程分析的文章就介绍到这了



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有