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模仿瑞幸咖啡菜單物品列表,以爲文章不錯的喜歡的小夥伴能夠關注加分享,也歡迎你們前來探討交流。
相關文章
相關標籤/搜索