介绍
RecyclerView的ItemDecoration是用来在RecyclerView的子项之间添加装饰(如分隔线、边距等)的类。它允许你在不修改RecyclerView子项布局的情况下,通过绘制在子项周围来改变它们的外观和间距。
主要用途
- 添加分隔线: 可以是水平或垂直的线条,用于将列表项分隔开。
- 设置边距: 可以增加列表项的边缘空间,改变它们之间的间距。
- 自定义装饰: 可以根据需求自定义复杂的装饰,如根据条件显示不同类型的分隔线或边距。
示例代码
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
val itemDecoration = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
recyclerView.addItemDecoration(itemDecoration)
RecyclerView.ItemDecoration介绍
RecyclerView.ItemDecoration是一个抽象类,用于定义在RecyclerView中绘制装饰的规范。我们需要继承并实现它的几个方法来实现自定义的装饰效果:
方法解析
- onDraw: 在RecyclerView的子项下方绘制装饰,例如分隔线。这些内容在子项视图之前绘制,因此会显示在视图的底部。
- onDrawOver: 在RecyclerView的子项上方绘制装饰,例如悬浮效果。这些内容在子项视图之后绘制,因此会显示在视图的顶部。
- getItemOffsets: 为每个子视图设置装饰的空间偏移,通常用于为分隔线预留空间。
DividerItemDecoration
DividerItemDecoration是官方提供的一个默认的ItemDecoration实现,用于在RecyclerView的子项之间添加分隔线。它可以根据需要设置分隔线的样式、颜色等属性。
onDraw方法示例
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (parent.getLayoutManager() == null || mDivider == null) {
return;
}
if (mOrientation == VERTICAL) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
在onDraw方法中,根据分隔线的方向(垂直或水平),调用对应的绘制方法,如drawVertical用于绘制垂直分隔线。
drawVertical方法实现
private void drawVertical(Canvas canvas, RecyclerView parent) {
// 保存画布当前状态
canvas.save();
final int left;
final int right;
if (parent.getClipToPadding()) {
// 如果RecyclerView设置了clipToPadding,考虑Padding的影响
left = parent.getPaddingLeft();
right = parent.getWidth() - parent.getPaddingRight();
// 剪切画布,使其只在padding区域内绘制
canvas.clipRect(left, parent.getPaddingTop(), right,
parent.getHeight() - parent.getPaddingBottom());
} else {
left = 0;
right = parent.getWidth();
}
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
parent.getDecoratedBoundsWithMargins(child, mBounds);
// 计算分隔线的顶端和底端位置
final int bottom = mBounds.bottom + Math.round(child.getTranslationY());
final int top = bottom - mDivider.getIntrinsicHeight();
// 设置分隔线的绘制区域
mDivider.setBounds(left, top, right, bottom);
// 绘制分隔线
mDivider.draw(canvas);
}
// 恢复画布状态
canvas.restore();
}
在drawVertical方法中,我们首先保存了画布的当前状态,然后根据RecyclerView的设置(是否clipToPadding)确定绘制区域,并遍历子视图来绘制垂直方向的分隔线。
getItemOffsets方法示例
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (mDivider == null) {
outRect.set(0, 0, 0, 0);
return;
}
if (mOrientation == VERTICAL) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
getItemOffsets方法用于为每个子视图设置装饰的空间偏移,以便为分隔线预留必要的空间。