Android-UI布局---RecyclerView学习(四)匹配GridLayoutManager的ItemDecoration

该系列文章  如果想全方面学习,建议参考这个大牛的文章,写的真可以。

地址:http://blog.csdn.net/lmj623565791/article/details/45059587


ItemDecoration  下划线效果

在使用RecyclerView 的时候有三种东西是可以自己定义的   响应事件    分割线  动画效果

 mRecyclerView = findView(R.id.id_recyclerview);
//设置布局管理器  layout可以设置方向
//mRecyclerView.setLayoutManager(layout);
mRecyclerView.setLayoutManager( new GridLayoutManager( this , 4 ));
//设置adapter
mRecyclerView.setAdapter(adapter)
//设置Item增加、移除动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration( getActivity(), DividerItemDecoration.HORIZONTAL_LIST)); 

布局管理器有三种:
  1. LinearLayoutManager 现行管理器,支持横向、纵向。
  2. GridLayoutManager 网格布局管理器
  3. StaggeredGridLayoutManager 瀑布就式布局管理器

这节主要学习如何添加下划线:为 GridLayoutManager模式添加下划线    mRecyclerView.addItemDecoration()

主要修改的地方有两点: 
第一处:
//mRecyclerView.setLayoutManager(new LinearLayoutManager(this));  
mRecyclerView.setLayoutManager(new GridLayoutManager(this,4));

改为GridLayoutManager以后,对于分割线,前面的DividerItemDecoration就不适用了,主要是因为它在绘制的时候,

比如水平线,针对每个child的取值为:

final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
当水平或者垂直的时候,分割线左右长度很好确定, 因为每个Item一行,这样是没问题的。而GridLayoutManager时, 一行有多个childItem ,这样就多次绘制了,并且GridLayoutManager时, Item如果为最后一列(则右边无间隔线)或者为最后一行(底部无分割线)。


解决方法重写RecyclerView.ItemDecoration

public class DividerGridItemDecoration extends RecyclerView.ItemDecoration
{

	private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
	private Drawable mDivider;

	public DividerGridItemDecoration(Context context)
	{
		final TypedArray a = context.obtainStyledAttributes(ATTRS);
		mDivider = a.getDrawable(0);
		a.recycle();
	}

	@Override
	public void onDraw(Canvas c, RecyclerView parent, State state)
	{//这个时候垂直和水平方向都需要重新绘制
		drawHorizontal(c, parent);
		drawVertical(c, parent);
	}

	private int getSpanCount(RecyclerView parent)
	{
		// 列数
		int spanCount = -1;
		LayoutManager layoutManager = parent.getLayoutManager();
		if (layoutManager instanceof GridLayoutManager)
		{
			spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
		} else if (layoutManager instanceof StaggeredGridLayoutManager)
		{
			spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
		}
		return spanCount;
	}

	public void drawHorizontal(Canvas c, RecyclerView parent)
	{
		int childCount = parent.getChildCount();
		for (int i = 0; i < childCount; i++)
		{
			final View child = parent.getChildAt(i);
			final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
					.getLayoutParams();
			final int left = child.getLeft() - params.leftMargin;
			final int right = child.getRight() + params.rightMargin
					+ mDivider.getIntrinsicWidth();
			final int top = child.getBottom() + params.bottomMargin;
			final int bottom = top + mDivider.getIntrinsicHeight();
			mDivider.setBounds(left, top, right, bottom);
			mDivider.draw(c);
		}
	}

	public void drawVertical(Canvas c, RecyclerView parent)
	{
		final int childCount = parent.getChildCount();
		for (int i = 0; i < childCount; i++)
		{
			final View child = parent.getChildAt(i);

			final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
					.getLayoutParams();
			final int top = child.getTop() - params.topMargin;
			final int bottom = child.getBottom() + params.bottomMargin;
			final int left = child.getRight() + params.rightMargin;
			final int right = left + mDivider.getIntrinsicWidth();

			mDivider.setBounds(left, top, right, bottom);
			mDivider.draw(c);
		}
	}

	/**
	 * 判断是否是最后一列
	 */
	private boolean isLastColum(RecyclerView parent, int pos, int spanCount,int childCount)
	{
		LayoutManager layoutManager = parent.getLayoutManager();
		if (layoutManager instanceof GridLayoutManager)
		{
			if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
			{
				return true;
			}
		} else if (layoutManager instanceof StaggeredGridLayoutManager)
		{
			int orientation = ((StaggeredGridLayoutManager) layoutManager)
					.getOrientation();
			if (orientation == StaggeredGridLayoutManager.VERTICAL)
			{
				if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
				{
					return true;
				}
			} else
			{
				childCount = childCount - childCount % spanCount;
				if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
					return true;
			}
		}
		return false;
	}

	/**
	 * 是否是最后一行
	 */
	private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,int childCount)
	{
		LayoutManager layoutManager = parent.getLayoutManager();
		if (layoutManager instanceof GridLayoutManager)
		{
			childCount = childCount - childCount % spanCount;
			if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
				return true;
		} else if (layoutManager instanceof StaggeredGridLayoutManager)
		{
			int orientation = ((StaggeredGridLayoutManager) layoutManager)
					.getOrientation();
			// StaggeredGridLayoutManager 且纵向滚动
			if (orientation == StaggeredGridLayoutManager.VERTICAL)
			{
				childCount = childCount - childCount % spanCount;
				// 如果是最后一行,则不需要绘制底部
				if (pos >= childCount)
					return true;
			} else
			// StaggeredGridLayoutManager 且横向滚动
			{
				// 如果是最后一行,则不需要绘制底部
				if ((pos + 1) % spanCount == 0)
				{
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public void getItemOffsets(Rect outRect, int itemPosition,
			RecyclerView parent)
	{
		int spanCount = getSpanCount(parent);
		int childCount = parent.getAdapter().getItemCount();
		if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
		{
			outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
		} else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
		{
			outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
		} else
		{
			outRect.set(0, 0, mDivider.getIntrinsicWidth(),
					mDivider.getIntrinsicHeight());
		}
	}
}


主要在getItemOffsets方法中,去判断如果是最后一行,则不需要绘制底部;如果是最后一列,则不需要绘制右边,整个判断也考虑到了StaggeredGridLayoutManager的横向和纵向,所以稍稍有些复杂。最重要还是去理解,如何绘制什么的不重要。一般如果仅仅是希望有空隙,还是去设置item的margin方便。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值