Recycleview模仿瑞幸咖啡菜单物品列表

嗨,你终于来啦 ~ 等你很久啦~ 喜欢的小伙伴欢迎关注,我会按期分享Android知识点及解析,还会不断更新的BATJ面试专题,欢迎你们前来探讨交流,若有好的文章也欢迎投稿android

前言

RecycleView的使用

RecyclerView是Google在API 21下support.V7包里的控件,用来替代ListView。
官网对RecycleView的描述为:A flexible view for providing a limited window into a large data set。面试

1、使用RecycleView的前提条件

想使用RecycleView,必定要在build.gradle中引入compile 'com.android.support:recyclerview-v7:24.0.0'依赖。数组

2、使用RecycleView的优缺点

优势:

  • RecycleView强制封装ViewHolder
  • 至关轻松的设置布局管理器以控制Item的布局方式,横向、竖向以及瀑布流方式
  • 可设置Item操做的动画,删除或者添加等
  • 经过ItemDecoration,控制Item间的间隔,可本身绘制

缺点:

  • 须要本身实现OnItemClickListener点击事件(这么实用的需求,Google居然让咱们本身实现...)

不过我认为Recycleview的ItemDecoration很是强大,你可使用它实现listview的分割线,悬浮窗,甚至一些很是炫的动画~bash

效果图

Recycleview模仿瑞幸咖啡菜单物品列表


ItemDecoration

  • onDraw():和普通view的onDraw差很少,就是绘制在画布上绘制东西。
  • onDrawOver():就是基于onDraw上再次绘制点东西,over的意思。
  • getItemOffsets():Recycleview能够经过他拿到每个item的间距,因此只须要控制这个间距,并在间距里利用onDrawOver再绘制你想绘制的东西。

实现这个的思路,咱们只须要在指定的的行数经过getItemOffsets预留出咱们要空出的高度,而后经过onDrawOver绘制出你所但愿的view便可。

1.手动构造数据格式,以下,返回list

Goods goods1 = new Goods("人气TOP", "正果拿铁1", "Y27", "默认:大/单糖/热");
Goods goods99 = new Goods("人气TOP", "正果拿铁2", "Y27", "默认:大/单糖/热");
Goods goods91 = new Goods("人气TOP", "正果拿铁3", "Y27", "默认:大/单糖/热");
Goods goods2 = new Goods("大师咖啡", "拿铁", "Y27", "默认:大/单糖/热");
Goods goods3 = new Goods("大师咖啡", "香草拿铁", "Y24", "默认:大/单糖/热");
Goods goods4 = new Goods("大师咖啡", "焦糖拿铁", "Y26", "默认:大/半糖/热");
List<Goods> list = new ArrayList<>();复制代码

2.书写本身的ItemDecoration

  • getItemOffsets预留空间,只须要在每一个数组的第一个数据预留一个高度,好比第一我的气TOP,第一个大师咖啡。
第一个必须预留,当前位置的name和前一个不相等则为预留空间
  @Override
public boolean isParent(int position) {
    if (position == 0) return true;
        if (!list.get(position).getType().equals(list.get(position - 1).getType()))
            return true;
    return false;
}
//是否为当前最后一个item
protected boolean lastOneInGroup(int position) {
        String parentName = mDecorListener.parentName(position);
        String nextGroupName;
        try {
            nextGroupName = mDecorListener.parentName(position + 1);
        } catch (Exception e) {
            nextGroupName = null;
        }
        if (nextGroupName == null) {
            return false;
        }
        return !TextUtils.equals(parentName, nextGroupName);//与下一行的name不同说明当前是最后一行
    }

由上isParent判断是第一个的返回你要预留的高度大小,不然为不须要空间0
 @Override
  public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        int position = parent.getChildAdapterPosition(view);
        if (parent.getLayoutManager() instanceof LinearLayoutManager && mDecorListener.isParent(position)) {
            outRect.top = decorationHeight;
            return;
        }
        outRect.top = 0;
    }
复制代码
  • 在预留的空间上画上你的view
@Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
        final int itemCount = state.getItemCount(); 所有item的数量
        final int childCount = parent.getChildCount(); 可看见的排除悬停的分割线的个数
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();
        for (int i = 0; i < childCount; i++) {
            View childView = parent.getChildAt(i);
            int position = parent.getChildAdapterPosition(childView);//就是当前可见每一行的position,从0开始
            //默认第一个就是有个Group
            if (mDecorListener.isParent(position) || i == 0) {//中第一个位置和可见的第一个才有这个悬停
                //绘制悬浮,
                int bottom = Math.max(decorationHeight, (childView.getTop() + parent.getPaddingTop()));
                //决定当前顶部第一个悬浮Group的bottom,拿到item高度和规定高度对比,只是选择一个合适的高度定义分割线
                if (position + 1 < itemCount) {
                    //下一组的第一个View接近头部
                    int viewBottom = childView.getBottom();
                    if (lastOneInGroup(position) && viewBottom < bottom) {
                        bottom = viewBottom;                    //若是这个关掉,会覆盖,顶上去效果失去,其实viewBottom逐渐变为0,这样动态的放置即将消失的悬浮拦,看上去就是下一个悬浮拦顶上来的
                    }
                }
                drawDecoration(c, position, left, right, bottom, parent);
                stickyHeaderPosArray.put(position, bottom);
            } 
        }
    }

    private void drawDecoration(Canvas c, int position, int left, int right, int bottom, RecyclerView parent) {
        c.drawRect(left, bottom - decorationHeight, right, bottom, mGroutPaint);
        Paint.FontMetrics fm = mTextPaint.getFontMetrics();
        //文字竖直居中显示
        float baseLine = bottom - (decorationHeight - (fm.bottom - fm.top)) / 2 - fm.bottom;
        //获取文字宽度
        mSideMargin = Math.abs(mSideMargin);
        c.drawText(mDecorListener.parentName(position), left + mSideMargin, baseLine, mTextPaint);//x轴,baseLine
        Rect rect = new Rect();//为了获得当前text的属性
        mTextPaint.getTextBounds(mDecorListener.parentName(position), 0, mDecorListener.parentName(position).length(), rect);
        //绘制那条横线
        c.drawLine(left + mSideMargin * 2 + rect.width(), baseLine - rect.height() / 2, parent.getWidth() -
                mSideMargin, baseLine - rect.height() / 2, mTextPaint);

    }

复制代码



  • 本文主要实现了Recycleview模仿瑞幸咖啡菜单物品列表,以为文章不错的喜欢的小伙伴能够关注加分享,也欢迎你们前来探讨交流。
相关文章
相关标签/搜索