1. ItemDecoration类的定义
ItemDecoration-->RecycleView的item系统间距以及系统item绘制封装类
/**
* ItemDecoration允许程序对适配器的数据源中的特殊的条目
* view 添加一些特别的图形和布局的偏移,这被用于在条目之
* 间画间隔线,高亮显示,视觉分组界限和更多。
* 所有的ItemDecorations
* <p>所有的ItemDecorations都是按照它们添加的顺序绘制的,
* 在所有的条目view绘制之前
* (in {@link ItemDecoration#onDraw(Canvas, RecyclerView, RecyclerView.State) onDraw()}
* 在所有的条目view绘制之后 (in {@link ItemDecoration#onDrawOver(Canvas, RecyclerView,
* RecyclerView.State)}.</p>
*/
public abstract static class ItemDecoration {
...
...
}
2. ItemDecoration的方法分析
此类下的六个方法有三个为过时方法,只需要复写另外三个未过时的方法即可,谷歌对这三个方法的定义如下:
- 在提供给RecyclerView的Canvas中绘制任何适当的装饰。 此方法绘制的任何内容将在绘制项目视图之前绘制, 因此将被视图覆盖.
public void onDraw(Canvas c, RecyclerView parent, State state{
onDraw(c, parent);
}
- 在提供给RecyclerView的Canvas中绘制任何适当的装饰。 此方法绘制的任何内容将在绘制项目视图之后绘制, 因此将覆盖视图
public void onDrawOver(Canvas c, RecyclerView parent, State state) {
onDrawOver(c, parent);
}
- 检索给定条目的所有偏移量, outRect 的每个字段指定条目视图应该被插入的像素大小,类似于填充或边距。默认实现将outRect的边界设置为0并返回。
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
getItemOffsets(outRect, ((LayoutParams)view.getLayoutParams()).getViewLayoutPosition(), parent);
}
注:onDraw 和 onDrawOver的区别在于,若未规定条目视图的左上右下的偏移量,在条目视图的基础上,使用canvas 所做的任何装饰,前者会被条目视图所覆盖,而后者方法则会在条目视图的基础上作画。
3. 封装 getItemOffsets
- 通过构造函数传入左上右下的间距
private int mSpaceHorizontal;
private int mSpaceVertical;
private Paint mPaint;
DividerDecoration(Activity activity, int spaceHorizontal, int spaceVertical) {
mSpaceHorizontal = spaceHorizontal;
mSpaceVertical = spaceVertical;
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
mPaint.setColor(ContextCompat.getColor(activity, android.R.color.transparent));
}
DividerDecoration(Activity activity, int color, int spaceHorizontal, int spaceVertical) {
mSpaceHorizontal = spaceHorizontal;
mSpaceVertical = spaceVertical;
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
mPaint.setColor(ContextCompat.getColor(activity, color));
}
- 筛选RecycleView的布局管理器 ,对应做单独处理
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
layoutGridItem(outRect, view, parent, (GridLayoutManager) layoutManager);
} else if (layoutManager instanceof LinearLayoutManager) {
layoutLinearItem(outRect, view, parent, (LinearLayoutManager) layoutManager);
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
layoutStaggeredItem(outRect, view, parent, (StaggeredGridLayoutManager) layoutManager);
}
}
- LinearLayoutManager 的布局偏移封装
private void layoutLinearItemSpace(Rect outRect, View view, RecyclerView parent, LinearLayoutManager linearManager) {
int viewPosition = parent.getChildAdapterPosition(view);
if (linearManager.getOrientation() == LinearLayoutManager.VERTICAL) {
outRect.left = mSpaceHorizontal;
outRect.right = mSpaceHorizontal;
if (viewPosition == 0) {
outRect.top = mSpaceVertical;
outRect.bottom = mSpaceVertical / 2;
} else if (viewPosition == linearManager.getItemCount() - 1) {
outRect.top = mSpaceVertical / 2;
outRect.bottom = mSpaceVertical;
} else {
outRect.top = mSpaceVertical / 2;
outRect.bottom = mSpaceVertical / 2;
}
} else {
outRect.top = mSpaceVertical;
outRect.bottom = mSpaceVertical;
if (viewPosition == 0) {
outRect.left = mSpaceHorizontal;
outRect.right = mSpaceHorizontal / 2;
} else if (viewPosition == linearManager.getItemCount() - 1) {
outRect.left = mSpaceHorizontal / 2;
outRect.right = mSpaceHorizontal;
} else {
outRect.left = mSpaceHorizontal / 2;
outRect.right = mSpaceHorizontal / 2;
}
}
}
- GridLayoutManager 的布局偏移封装
private void layoutGridItemSpace(Rect outRect, View view, RecyclerView parent, GridLayoutManager gridManager) {
int viewPosition = parent.getChildAdapterPosition(view);
int spanCount = gridManager.getSpanCount();
int index = viewPosition % spanCount;
if (viewPosition < spanCount) {//第一行
outRect.top = mSpaceVertical;
outRect.bottom = mSpaceVertical / 2;
} else if (viewPosition / spanCount == (gridManager.getItemCount() - 1) / spanCount) {//多宫格如何判断最后一行?
outRect.top = mSpaceVertical / 2;
outRect.bottom = mSpaceVertical;
} else {
outRect.top = mSpaceVertical / 2;
outRect.bottom = mSpaceVertical / 2;
}
if (index == 0) {//第一列
outRect.left = mSpaceHorizontal;
outRect.right = mSpaceHorizontal / 2;
} else if (index == spanCount - 1) {//最后一列
outRect.left = mSpaceHorizontal / 2;
outRect.right = mSpaceHorizontal;
} else {
outRect.left = mSpaceHorizontal / 2;
outRect.right = mSpaceHorizontal / 2;
}
}
- StaggeredGridLayoutManager的布局偏移封装
private void layoutStaggeredItemSpace(Rect outRect, View view, RecyclerView parent, StaggeredGridLayoutManager staggeredManager) {
}
- LinearLayoutManager 的布局偏移颜色封装
private void drawLinearItemSpace(Canvas c, RecyclerView parent, LinearLayoutManager linearManager) {
if (linearManager.getOrientation() == LinearLayoutManager.VERTICAL) {
for (int viewPosition = 0; viewPosition < linearManager.getItemCount(); viewPosition++) {
View childView = parent.getChildAt(viewPosition);
if (childView == null) {
continue;
}
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) childView.getLayoutParams();
int left;
int top;
int right;
int bottom;
left = childView.getLeft() - params.leftMargin;
right = childView.getRight() + params.rightMargin;
top = childView.getBottom() + params.bottomMargin;
bottom = top + mSpaceVertical;
c.drawRect(left, top, right, bottom, mPaint);
if (viewPosition == 0) {
top = childView.getTop() - params.topMargin - mSpaceVertical;
bottom = top + mSpaceVertical;
c.drawRect(left, top, right, bottom, mPaint);
}
}
} else {
for (int viewPosition = 0; viewPosition < linearManager.getItemCount(); viewPosition++) {
View childView = parent.getChildAt(viewPosition);
if (childView == null) {
continue;
}
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) childView.getLayoutParams();
int left;
int top;
int right;
int bottom;
left = childView.getRight() + params.rightMargin;
top = childView.getTop() - params.topMargin;
right = left + mSpaceHorizontal;
bottom = childView.getBottom() + params.bottomMargin;
c.drawRect(left, top, right, bottom, mPaint);
if(viewPosition == 0) {
left = childView.getLeft() - params.leftMargin - mSpaceHorizontal;
top = childView.getTop() - params.topMargin;
right = left + mSpaceHorizontal;
bottom = childView.getBottom() + params.bottomMargin;
c.drawRect(left, top, right, bottom, mPaint);
}
}
}
}
- GridLayoutManager 的布局颜色填充封装
private void drawGridItemSpace(Canvas c, RecyclerView parent, GridLayoutManager gridManager) {
for (int viewPosition = 0; viewPosition < gridManager.getItemCount(); viewPosition++) {
View childView = parent.getChildAt(viewPosition);
if (childView == null) {
continue;
}
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) childView.getLayoutParams();
int spanCount = gridManager.getSpanCount();
int index = viewPosition % spanCount;
int left;
int top;
int right;
int bottom;
left = childView.getLeft() - params.leftMargin;
right = childView.getRight() + params.rightMargin + mSpaceHorizontal;
if (viewPosition < spanCount) {//第一行
top = childView.getTop() - params.topMargin - mSpaceVertical;
bottom = top + mSpaceVertical;
c.drawRect(left, top, right, bottom, mPaint);
top = childView.getBottom() + params.bottomMargin;
bottom = top + mSpaceVertical;
c.drawRect(left, top, right, bottom, mPaint);
} else {
top = childView.getBottom() + params.bottomMargin;
bottom = top + mSpaceVertical;
c.drawRect(left, top, right, bottom, mPaint);
}
if (index == 0) {//第一列
top = childView.getTop() - params.topMargin;
bottom = childView.getBottom() + params.bottomMargin + mSpaceVertical;
left = childView.getLeft() - params.leftMargin - mSpaceHorizontal;
right = left + mSpaceHorizontal;
c.drawRect(left, top, right, bottom, mPaint);
top = childView.getTop() - params.topMargin;
bottom = childView.getBottom() + params.bottomMargin;
left = childView.getRight() + params.rightMargin;
right = left + mSpaceHorizontal;
c.drawRect(left, top, right, bottom, mPaint);
if (viewPosition == 0) {
top = childView.getTop() - params.topMargin - mSpaceVertical;
bottom = top + mSpaceVertical;
left = childView.getLeft() - params.leftMargin - mSpaceHorizontal;
right = left + mSpaceHorizontal;
c.drawRect(left, top, right, bottom, mPaint);
}
} else {
top = childView.getTop() - params.topMargin;
bottom = childView.getBottom() + params.bottomMargin;
left = childView.getRight() + params.rightMargin;
right = left + mSpaceHorizontal;
c.drawRect(left, top, right, bottom, mPaint);
}
}
}
- StaggeredGridLayoutManager的布局偏移颜色填充封装
StaggeredGridLayoutManager 相关的目前正在研究,后面会补充完善