本帖最后由 小鲁哥哥 于 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);
}
}
}
}
}
}
|