被分割线造成的痛苦面具

被分割线造成的痛苦面具

问题描述:

了解到自定义分割线要在自定义一个RecyclerView.ItemDecoration类,但是在网上的解答和里面用的方法都让我一脸懵逼,实在是痛苦面具带来好几天都搞不懂这些代码到底怎样绘制的分割线,已经浏览过很多类似的帖子了下面是找了相对简单的一个

源码在此:https://blog.csdn.net/liuxingrong666/article/details/83178213

http://img1.sycdn.imooc.com//climg/605beb0709cd41d506710418.jpg例如这里LayoutParams代表的是什么含义(虽然已经查过但还是觉得云里雾里);二是left right top bottom是绘制的分割线的长度吗,它们这些值真的看不懂;还有最后这第一行画顶部分割线又是什么意思呢

http://img1.sycdn.imooc.com//climg/605bec360947d84006080541.jpg这边最后一列不是应该不需要绘制左边吗?

http://img1.sycdn.imooc.com//climg/605beca6094ce72206440572.jpg最后一行不是应该不需要绘制顶部吗?真的看了好几天代码好像一个蹦都看不懂

相关代码:

public class GridItemDivider extends RecyclerView.ItemDecoration {

private String TAG = getClass().getSimpleName();
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
private Drawable divider;

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

public GridItemDivider(Drawable drawable) {
divider = drawable;
}

public GridItemDivider(int height, int color) {
GradientDrawable shapeDrawable = new GradientDrawable();
shapeDrawable.setColor(color);
shapeDrawable.setShape(GradientDrawable.RECTANGLE);
shapeDrawable.setSize(height, height);
divider = shapeDrawable;
}


@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {

drawHorizontal(c, parent);
drawVertical(c, parent);

}

private int getSpanCount(RecyclerView parent) {
// 列数
int spanCount = -1;
RecyclerView.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(); //获取可见item的数量
int spanCount = getSpanCount(parent);
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
+ divider.getIntrinsicWidth();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + divider.getIntrinsicHeight();
divider.setBounds(left, top, right, bottom);
divider.draw(c);
if (i < spanCount) { //画第一行顶部的分割线
drawHorizontalForFirstRow(c, child);
}
}
}

private void drawHorizontalForFirstRow(Canvas c, View child) {
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
int left = child.getLeft() - params.leftMargin - divider.getIntrinsicWidth();
int top = child.getTop() - params.topMargin - divider.getIntrinsicHeight();
int right = child.getRight() + params.rightMargin + divider.getIntrinsicWidth();
int bottom = top + divider.getIntrinsicHeight();
divider.setBounds(left, top, right, bottom);
divider.draw(c);
}

private void drawVerticalForFirstColum(Canvas c, View child) {
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
int left = child.getLeft() - params.leftMargin - divider.getIntrinsicWidth();
int top = child.getTop() - params.topMargin;
int right = child.getLeft() - params.leftMargin;
int bottom = top + child.getHeight() + divider.getIntrinsicHeight();
divider.setBounds(left, top, right, bottom);
divider.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 + divider.getIntrinsicWidth();
divider.setBounds(left, top, right, bottom);
divider.draw(c);
if (isFirstColum(parent, i, getSpanCount(parent))) { //画第一列左边分割线
drawVerticalForFirstColum(c, child);
}
}
}

private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
int childCount) {
RecyclerView.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) {
RecyclerView.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();
if (orientation == StaggeredGridLayoutManager.VERTICAL) {
childCount = childCount - childCount % spanCount;
// 如果是最后一行,则不需要绘制底部
if (pos >= childCount)
return true;
} else
{
// 如果是最后一行,则不需要绘制底部
if ((pos + 1) % spanCount == 0) {
return true;
}
}
}
return false;
}

//是否为第一列
private boolean isFirstColum(RecyclerView parent, int pos, int spanCount) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) { //网格布局
if ((pos + 1) % spanCount == 1) {
return true;
}
}
return false;
}

//是否为第一行
private boolean isFirstRaw(int pos, int spanCount) {
if (pos < spanCount) {
return true;
}
return false;
}

@Override
public void getItemOffsets(Rect outRect, int itemPosition,
RecyclerView parent) {
int spanCount = getSpanCount(parent); //列数

if (itemPosition == 0) { //第一行第一个,四边都画
outRect.set(divider.getIntrinsicWidth(), divider.getIntrinsicHeight(),
divider.getIntrinsicWidth(), divider.getIntrinsicHeight());
} else if (isFirstRaw(itemPosition, spanCount)) { //第一行,画上下右三边
outRect.set(0, divider.getIntrinsicHeight(), divider.getIntrinsicWidth(), divider.getIntrinsicHeight());
} else if (isFirstColum(parent, itemPosition, spanCount)) { //第一列,画左右下三边
outRect.set(divider.getIntrinsicWidth(), 0, divider.getIntrinsicWidth(), divider.getIntrinsicHeight());
} else { //其他,画右下两边
outRect.set(0, 0, divider.getIntrinsicWidth(), divider.getIntrinsicHeight());
}

}

}


正在回答

登陆购买课程后可参与讨论,去登陆

1回答

同学,你好!1)LayoutParams,顾名思义,就是布局参数。在布局文件XML里的写法例如android:layout_width = "match_parent"之类的参数。2)这4个值是什么,从setBounds(int left, int top, int right, int bottom)说起,这个四参数指的是drawable将在被绘制在canvas的哪个矩形区域内。3)就是画第一行图片上面的那条分割线。

祝:学习愉快!


  • AgonyX 提问者 #1

    但是看代码

    final int left = child.getLeft() - params.leftMargin;
    final int right = child.getRight() + params.rightMargin
    + divider.getIntrinsicWidth();

    这就是左和右绘制的方式都不一样,凭想象真的看不出这样依据是什么

    2021-03-25 17:54:17
  • AgonyX 提问者 #2

    其实作业里面的分割线完全可以不需要重写itemdecoration对吧?只需要里面套一个cardview就好了吧,间距的话倒是可以用itemdecoration改一改,是这个原理吗

    2021-03-26 11:49:25
  • 好帮手慕雪 回复 提问者 AgonyX #3

    是的,作业里的分割线没必要自定义

    2021-03-26 11:55:35
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
2.Android 网络操作与流行框架
  • 参与学习           人
  • 提交作业       220    份
  • 解答问题       1800    个

本阶段是联网及数据处理的必备技能。课程从网络基础知识到线程间协同工作、异步下载处理;从文件存储、到轻量级数据库SQLite的使用;最后利用最流程的第三方框架助你快速开发企业级APP。

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师