RecyclerView.ItemDecoration 使用总结

最近尝试自己使用了一下RecyclerView,在设置分割线的时候,需要自己继承ItemDerocation类,并重写onDraw()和getItemOffets()方法。效果如下图:
这里写图片描述
白色的选项框就是用recyclerView实现的。

下面贴出ItemDecoration的代码:

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;

public class DividerItemDecoration extends  RecyclerView.ItemDecoration {
    private static final int[] ATTRS = new int[] {
      android.R.attr.listDivider
      //使用的是系统内置的分割线
    };

public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

private Drawable mDivider;

private int mOriention;

public DividerItemDecoration(Context context, int oriention) {
    final TypedArray typedArray = context.obtainStyledAttributes(ATTRS);
    mDivider = typedArray.getDrawable(0);
    typedArray.recycle();//必须用recycle()回收,否则会对下次属性设置产生影响。
    setOriention(oriention);
}

public void setOriention(int oriention) {
     if (oriention != VERTICAL_LIST && oriention != HORIZONTAL_LIST ) {
         throw new IllegalArgumentException("invalid oriention");
     }
    mOriention = oriention;
}

@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    super.onDraw(c, parent, state);
    if (mOriention == VERTICAL_LIST) {
        drawVertical(c, parent);
    } else {
        //再把横向分割写了,虽然用不到
        drawHorizontal(c, parent);
    }
}

private void drawHorizontal(Canvas c, RecyclerView parent) {
    final int top = parent.getPaddingTop();
    final int bottom = parent.getHeight() - parent.getPaddingRight();

    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 left = child.getRight() + params.rightMargin;
        final int right = left + mDivider.getIntrinsicWidth();
        mDivider.setBounds(left,top,right,bottom);
        mDivider.draw(c);
    }
}

private void drawVertical(Canvas c, RecyclerView parent) {
    final int left = parent.getPaddingLeft();
    final int right = parent.getWidth() - parent.getPaddingRight();

    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.getBottom() + params.bottomMargin;
        Log.d("params.bottomMargin",  "" + params.bottomMargin);
        Log.d("child.getBottom()", "第" + i+ "个" + child.getBottom());
        /*这里想查明child.getBottom()和params.bottomMargin是如何取值的。logo显示,getBottom应该显示的是每个item底部到屏幕顶部的距离;bottomMargin取值都是0,所以不好判断*/

        final int bottom = top + mDivider.getIntrinsicHeight();
        mDivider.setBounds(left,top, right, bottom);
        mDivider.draw(c);
    }
}

//这个函数设置分割线的绘制范围。
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    super.getItemOffsets(outRect, view, parent, state);
    if (mOriention == VERTICAL_LIST) {
        outRect.set(0,0,0,mDivider.getIntrinsicHeight());
    } else {
        outRect.set(0,0,mDivider.getIntrinsicWidth(),0);
    }
}

}

查阅资料,发现,可以自定义分割线样式
现在stytle中设置新的android:listDivider值:


@drawable/divider_bg

然后,在drawable中创建一个divider_bg:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想在 `RecyclerView` 的 `ItemDecoration` 中获取当前列的位置,可以使用 `GridLayoutManager` 中的 `getSpanCount()` 方法获得列数,然后使用 `getPosition()` 方法获得当前 item 在整个列表中的位置,再计算出当前列的位置。 以下是一个示例代码: ```java public class MyItemDecoration extends RecyclerView.ItemDecoration { private int mSpacing; private int mSpanCount; public MyItemDecoration(int spacing, int spanCount) { mSpacing = spacing; mSpanCount = spanCount; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { int position = parent.getChildAdapterPosition(view); int column = position % mSpanCount; outRect.left = column * mSpacing / mSpanCount; outRect.right = mSpacing - (column + 1) * mSpacing / mSpanCount; outRect.bottom = mSpacing; if (position < mSpanCount) { outRect.top = mSpacing; } else { outRect.top = 0; } } } ``` 在这个例子中,`MyItemDecoration` 继承了 `RecyclerView.ItemDecoration`,并在其构造函数中接收列间距和列数作为参数。 在 `getItemOffsets()` 方法中,我们首先获取当前 item 在整个列表中的位置,然后计算出当前列的位置。`column` 的计算方法是 `position % mSpanCount`,即当前位置除以列数的余数。 接下来,我们根据列的位置计算出左、右、上和下的偏移量。左偏移量等于当前列的位置乘以列间距再除以列数,右偏移量等于列间距减去左偏移量,下偏移量等于列间距,而上偏移量在第一行的 item 中为列间距,其它行的 item 中为 0。 最后,我们将计算出的偏移量设置给 `outRect` 对象,它会在 `RecyclerView` 中绘制 item 时被使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值