ItemDecoration 的封装
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 相关的目前正在研究,后面会补充完善