开发者

Android RecyclerView实现吸顶动态效果流程分析

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

    Android RecyclerView实现吸顶动态效果流程分析

    一、ItemDecoration

    Android RecyclerView实现吸顶动态效果流程分析

    ItemDecoration 允许应用给具体的 View 添加具体的图画或者 layout 的偏移,对于绘制 View之间的分割线,视觉分组边界等等是非常有用的。

    Android RecyclerView实现吸顶动态效果流程分析

    当我们调用 addItemDecoration() 方法添加 decoration 的时候,RecyclerView 就会调用该类的 onDraw 方法去绘制分割线,也就是说:分割线是绘制出来的。

    RecyclerView.addItemDecoration()

    Android RecyclerView实现吸顶动态效果流程分析

    RecyclerView.ItemDecoration,该类为抽象类,官方目前只提供了一个实现类 DividerItemDecoration。

    public abstract static class ItemDecoration

    public class DividerItemDecoration extends RecyclerView.ItemDecoration

    里面有3个方法:

    Android RecyclerView实现吸顶动态效果流程分析

    onDraw(): 在提供给RecyclerView的画布上绘制任何适当的装饰。通过此方法绘制的任何内容都将在绘制项目视图之前被绘制,因此将出现在视图的下方。

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

    绘制效果

    Android RecyclerView实现吸顶动态效果流程分析

    Android RecyclerView实现吸顶动态效果流程分析

    onDrawOver():在提供给RecyclerView的画布上绘制任何适当的装饰。通过这种方法绘制的任何内容都将在项目视图被绘制之后被绘制,因此将出现在视图上方。

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

    绘制效果

    Android RecyclerView实现吸顶动态效果流程分析

    Android RecyclerView实现吸顶动态效果流程分析

    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的实现细节略。

    Android RecyclerView实现吸顶动态效果流程分析

    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);
                }
            }

    实现效果

    Android RecyclerView实现吸顶动态效果流程分析

    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() >javascript=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(grou开发者_Python开发pName, 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);
                    }
                }
           }
        }

    实现效果

    Android RecyclerView实现吸顶动态效果流程分析

    4android、实现吸顶效果编程

    因为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.minjavascript(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);
                }
            }
        }

    实现效果

    Android RecyclerView实现吸顶动态效果流程分析

    完整demo

    链接: https://pan.baidu.com/s/11I8dtWts3BZjYMgNvzanTw?pwd=bvx9

    到此这篇关于android RecyclerView实现吸顶动态效果流程分析的文章就介绍到这了,更多相关Android RecyclerView内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜