黑马程序员技术交流社区

标题: 【济南中心】利用RecyclerView的ItemDecoration实现item间的蛇形... [打印本页]

作者: 大山哥哥    时间: 2016-7-29 23:20
标题: 【济南中心】利用RecyclerView的ItemDecoration实现item间的蛇形...
本帖最后由 小鲁哥哥 于 2020-1-8 17:02 编辑

点击查看济南黑马校区最新开班计划


利用RecyclerView的ItemDecoration实现item间的蛇形连线。先上图大家看看效果:
原理很简单,就是重写ItemDecoration的getItemOffsets()方法设置item之间的边距,在onDraw()方法中根据item的位置来判断画横线还是竖线。

下面先来分析一下什么情况下画横向连接线,什么情况下画纵向连接线?首先来分析一下横向连接线,在每一行中,只要当前的item不是最后一列就向右画一条横向的连接线。但是有个特例就是当前是最后一行,最后一个item不在最后一列,就要把这种特殊情况过滤出来否则就会出现下图这样的情况:

所以我们在onDraw()方法中画横向连接线有两个判断条件
[Java] 纯文本查看 复制代码
 if ((position % COLUMN_CONT != (COLUMN_CONT - 1)) && (position != mItems.size() - 1)) {
                        c.drawLine(childRight - mSpace, y, childRight + mSpace, y, mLinePaint);
                    }


再来分析一下纵向连接线如何来画,情况好像比画横向连接线复杂了很多。分两种情况:
1.行的position是奇数时,第一列上的item向下画连接线,特殊情况就是当前是最后一行,如果不加以处理,就会出现下图的情况:

所以当前情况下的判断条件如下:
[AppleScript] 纯文本查看 复制代码
if (position % COLUMN_CONT == 0) {
                        //第一列中奇数行item与下一行第一个item连接,并且如果当前是最后一行也不画纵向连接线
                        if ((position / COLUMN_CONT) % 2 == 1 &&  position < mItems.size() - COLUMN_CONT) {
                            c.drawLine(x, childBotton - mSpace, x, childBotton + mSpace, mLinePaint);
                        }
                    }
                    



2.行的position是偶数时,最后一列上的item向下画连接线,这里面也有一种特殊情况,就是最后一行不能排满,如图:

处理方式要在最后一行前面补上空白item,将不能排满的item顶到后面去。也就说初始化数据时,如果最后一行不能排满并且position是奇数,就要在本行的前面加上空白item。
[AppleScript] 纯文本查看 复制代码
mItems.addAll(Arrays.asList(ITEMS));
                    temp.addAll(mItems.subList(0, ITEMS.length - (ITEMS.length) % COLUMN_CONT));
                    for (int i = 0; i < COLUMN_CONT - (ITEMS.length) % COLUMN_CONT; i++) {
                        temp.add("placeholder");
                    }
                    temp.addAll(mItems.subList(ITEMS.length - (ITEMS.length) % COLUMN_CONT, mItems.size()));
                    mItems = temp;

并且在onDraw()方法中要将添加的空白item过滤出来,否则:

正确显示效果如图:




[AppleScript] 纯文本查看 复制代码
package com.itheima.recyclerviewdemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private static final int COLUMN_CONT = 6;
    private static final String[] ITEMS = {"A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A"};
    private List<String> mItems;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv);
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, COLUMN_CONT, LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(gridLayoutManager);
        recyclerView.addItemDecoration(new ConnectorDecoration(this));
        recyclerView.setAdapter(new MyAdapter(this));
    }

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ItemHolder> {
        private LayoutInflater mLayoutInflater;
        private Context mContext;

        public MyAdapter(Context context) {
            mContext = context;
            mItems = new ArrayList<>();
            List<String> temp = new ArrayList<>();
            if (ITEMS.length % COLUMN_CONT == 0) {
                mItems.addAll(Arrays.asList(ITEMS));
            } else {
                if ((ITEMS.length / COLUMN_CONT) % 2 == 0) {
                    mItems.addAll(Arrays.asList(ITEMS));
                } else {
                    mItems.addAll(Arrays.asList(ITEMS));
                    temp.addAll(mItems.subList(0, ITEMS.length - (ITEMS.length) % COLUMN_CONT));
                    for (int i = 0; i < COLUMN_CONT - (ITEMS.length) % COLUMN_CONT; i++) {
                        temp.add("placeholder");
                    }
                    temp.addAll(mItems.subList(ITEMS.length - (ITEMS.length) % COLUMN_CONT, mItems.size()));
                    mItems = temp;
                }


            }
            mLayoutInflater = LayoutInflater.from(context);
        }

        @Override
        public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = mLayoutInflater.inflate(R.layout.item, parent, false);
            return new ItemHolder(view);
        }

        @Override
        public void onBindViewHolder(ItemHolder holder, int position) {
            if (mItems.get(position).equals("placeholder")) {
                holder.setText("");
                holder.tv.setBackgroundColor(Color.TRANSPARENT);
            } else {
                holder.tv.setBackgroundColor(mContext.getResources().getColor(R.color.colorLine));
                holder.setText(mItems.get(position));
            }

        }

        @Override
        public int getItemCount() {
            return mItems.size();
        }

        private ArrayList sortDatas(List<String> items) {
            ArrayList<String> tempItems = new ArrayList();
            int rowPostion = (items.size() - 1) / COLUMN_CONT;
            if ((items.size() - 1) % COLUMN_CONT != 0) {
                rowPostion = rowPostion + 1;
            }
            for (int i = 0; i < rowPostion - 1; i++) {
                if (i % 2 == 0) {
                    for (int j = 0; i < COLUMN_CONT - 1; j++) {

                        tempItems.add(items.get(i * COLUMN_CONT + j));
                    }
                } else {
                    for (int j = 0; i < COLUMN_CONT - 1; j++) {
                        if (i != rowPostion) {
                            tempItems.add(items.get((i + 1) * COLUMN_CONT - j));
                        }
                    }
                }
            }
            return tempItems;
        }

        public class ItemHolder extends RecyclerView.ViewHolder {
            private TextView tv;

            public ItemHolder(View itemView) {
                super(itemView);
                tv = (TextView) itemView.findViewById(R.id.item_tv);
            }

            public void setText(CharSequence text) {
                tv.setText(text);
            }
        }

    }

    public class ConnectorDecoration extends RecyclerView.ItemDecoration {
        private Paint mLinePaint;
        private int mSpace;

        public ConnectorDecoration(Context context) {
            super();
            mSpace = context.getResources().getDimensionPixelOffset(R.dimen.space_margin);
            int connectorWidth = context.getResources().getDimensionPixelOffset(R.dimen.connector_width);
            mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mLinePaint.setColor(context.getResources().getColor(R.color.colorLine));
            //设置连接线宽度
            mLinePaint.setStrokeWidth(connectorWidth);
        }

        /*
        设置每个item之间的边距
         */
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            outRect.set(mSpace, mSpace, mSpace, mSpace);
        }

        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            RecyclerView.LayoutManager manager = parent.getLayoutManager();
            for (int i = 0; i < parent.getChildCount(); i++) {
                View child = parent.getChildAt(i);
                int childLeft = manager.getDecoratedLeft(child);
                int childRight = manager.getDecoratedRight(child);
                int childTop = manager.getDecoratedTop(child);
                int childBotton = manager.getDecoratedBottom(child);
                //当前childview x轴方向的中间位置。
                int x = childLeft + ((childRight - childLeft) / 2);
                //当前childview y轴方向的中间位置。
                int y = childBotton + ((childTop - childBotton) / 2);
                int position = parent.getChildViewHolder(child).getLayoutPosition();
                if (!mItems.get(position).equals("placeholder")) {
                    //过滤出第一列上所有item的position
                    if (position % COLUMN_CONT == 0) {
                        //第一列中奇数行item与下一行第一个item连接,并且当前不是最后一个childview,并且如果当前是最后一行也不画纵向连接线
                        if ((position / COLUMN_CONT) % 2 == 1 && position < mItems.size() - COLUMN_CONT) {
                            c.drawLine(x, childBotton - mSpace, x, childBotton + mSpace, mLinePaint);
                        }
                        //过滤出最后一列上所有item的posiion
                    } else if (position % COLUMN_CONT == (COLUMN_CONT - 1)) {
                        //偶数行,最后一列向下画连接线,并且当前不是最后一个childview
                        if ((position / COLUMN_CONT) % 2 == 0 && (position != mItems.size() - 1)) {
                            c.drawLine(x, childBotton - mSpace, x, childBotton + mSpace, mLinePaint);
                        }
                    }
                    //当前childview不是每一行的最后一列,并且不是最后一个,画横向的连接线。
                    if ((position % COLUMN_CONT != (COLUMN_CONT - 1)) && (position != mItems.size() - 1)) {
                        c.drawLine(childRight - mSpace, y, childRight + mSpace, y, mLinePaint);
                    }
                }
            }
        }
    }
}







作者: 达文西叔叔    时间: 2016-7-30 12:18
我是来点赞的
作者: Shire    时间: 2016-7-30 15:24
前排酱油党!!!!!
作者: 流光    时间: 2016-7-31 18:12
虽然看不懂,但好像很厉害的样子
作者: 斧王就是我    时间: 2016-7-31 19:01
看不懂,还得继续学习,哈哈哈,加油吧,勿忘初心
作者: Frank_Ms1ZR    时间: 2016-7-31 19:28
mark一下
作者: 崇尚技术的菜鸟    时间: 2016-7-31 19:42
顶帖,日常顶帖
作者: 橘子哥    时间: 2016-8-1 09:54
蛇形连接,看起来好屌!
作者: 自渡。    时间: 2016-8-1 16:53
看不懂,打酱油
作者: mengqishiye    时间: 2016-8-2 01:33
加油↖(^ω^)↗↖(^ω^)↗
作者: 奥特珞珞猫咪喵    时间: 2016-8-3 16:50
学什么都一样,努力就会有付出的!
作者: 皇亚杰    时间: 2016-8-3 22:52
我也是来点赞的
作者: 阿沐沐    时间: 2016-8-7 23:17
高手在民间
作者: 戒0416    时间: 2016-8-8 14:49
我就是路过,不明觉厉
作者: miqideliwu    时间: 2016-8-9 23:08
23rssfgsfgssfsgssfgsgfs
作者: aiziji123    时间: 2016-8-16 21:32
大神啊,膜拜
作者: 丁丁丁    时间: 2016-8-17 18:48
表示真的看不懂啊!太高深了,还要继续努力
作者: 阿弥陀佛么么哒    时间: 2016-8-18 09:51
赞。…。……。…。…。…。……
作者: qbh1213    时间: 2016-8-19 17:17
表示看不懂
作者: gohw007    时间: 2016-8-21 11:33
写的真好
作者: gohw007    时间: 2016-8-22 06:35
很厉害,赞一个
作者: lifuzhe    时间: 2016-8-23 21:39
值得借鉴,谢谢
作者: lifuzhe    时间: 2016-8-23 21:50
很好,加油,棒棒哒
作者: LLL_LLL    时间: 2016-8-24 23:16
写的真好,学习了
作者: wzplol    时间: 2016-8-25 16:37
好高端就是看不懂啊咋办
作者: Tao_tao    时间: 2016-8-25 18:47
好像很牛的样纸!
作者: Abbiamo    时间: 2016-8-25 23:29
可以,很有效果
作者: chensc    时间: 2016-8-26 06:30
学习学习!
作者: Wade1982    时间: 2016-8-28 19:01
乐于分享的人必然会有好运
作者: 宾仔wang    时间: 2016-8-31 17:46
济南的帖子偏多呢




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2