RecycleView的ItemDecoration详解
ItemDecoration:顾名思义,就是给RecycleView的Item项做装饰的
1. 系统默认实现
DividerItemDecoration 是系统提供给我们的实现,可以实现 LinearLayoutManager 中的分割线效果,但是其他的 LayoutManager 就得我们自己写了
//添加分割线
recycle.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
默认样式如下:
DividerItemDecoration 我们可以通过修改系统参数的情况下自定义分割线效果
1、找到res/values/styles.xml,在其中声明android:listDivider属性,然后使用我们自己的样式
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!--添加默认分割线的样式-->
<item name="android:listDivider">@drawable/my_divider</item>
</style>
</resources>
2、在res/drawable目录下声明我们自己的样式my_divider.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:centerColor="#ff00ff"
android:endColor="#00ff00"
android:startColor="#0000ff"
android:type="linear" />
<size android:height="4dp"/>
</shape>
这样,使用自定义分割线后的样式如下:
2、 ItemDecoration 绘制顺序
ItemDecoration是一个抽象类,源码如下:
public abstract static class ItemDecoration {
/**
* Draw any appropriate decorations into the Canvas supplied to the RecyclerView.
* Any content drawn by this method will be drawn before the item views are drawn,
* and will thus appear underneath the views.
*
* @param c Canvas to draw into
* @param parent RecyclerView this ItemDecoration is drawing into
* @param state The current state of RecyclerView
*/
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull State state) {
onDraw(c, parent);
}
/**
* @deprecated
* Override {@link #onDraw(Canvas, RecyclerView, RecyclerView.State)}
*/
@Deprecated
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent) {
}
/**
* Draw any appropriate decorations into the Canvas supplied to the RecyclerView.
* Any content drawn by this method will be drawn after the item views are drawn
* and will thus appear over the views.
*
* @param c Canvas to draw into
* @param parent RecyclerView this ItemDecoration is drawing into
* @param state The current state of RecyclerView.
*/
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent,
@NonNull State state) {
onDrawOver(c, parent);
}
/**
* @deprecated
* Override {@link #onDrawOver(Canvas, RecyclerView, RecyclerView.State)}
*/
@Deprecated
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent) {
}
/**
* @deprecated
* Use {@link #getItemOffsets(Rect, View, RecyclerView, State)}
*/
@Deprecated
public void getItemOffsets(@NonNull Rect outRect, int itemPosition,
@NonNull RecyclerView parent) {
outRect.set(0, 0, 0, 0);
}
/**
* Retrieve any offsets for the given item. Each field of <code>outRect</code> specifies
* the number of pixels that the item view should be inset by, similar to padding or margin.
* The default implementation sets the bounds of outRect to 0 and returns.
*
* <p>
* If this ItemDecoration does not affect the positioning of item views, it should set
* all four fields of <code>outRect</code> (left, top, right, bottom) to zero
* before returning.
*
* <p>
* If you need to access Adapter for additional data, you can call
* {@link RecyclerView#getChildAdapterPosition(View)} to get the adapter position of the
* View.
*
* @param outRect Rect to receive the output.
* @param view The child view to decorate
* @param parent RecyclerView this ItemDecoration is decorating
* @param state The current state of RecyclerView.
*/
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view,
@NonNull RecyclerView parent, @NonNull State state) {
getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(),
parent);
}
}
抽取出核心方法翻译过来
public static abstract class ItemDecoration {
// 在itemView绘制完成之前调用,也就是说此方法draw出来的效果将会在itemView的下面
public void onDraw(Canvas c, RecyclerView parent, State state) {
onDraw(c, parent);
}
//与onDraw相反,draw出来的效果将叠加在itemView的上面
public void onDrawOver(Canvas c, RecyclerView parent, State state) {
onDrawOver(c, parent);
}
//算通过配置outRect来设置itemView的inset边界,相当于设置itemView的margin
@Deprecated
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
outRect.set(0, 0, 0, 0);
}
}
如图所示:
outRect 设置就是 item 4周的 magin ,然后配合 onDraw ,onDrawOver 方法操作
onDraw 相当于画背景,在 item 之前绘制,onDrawOver 相当于画前景,在 item 之后绘制
3. ItemDecoration 是可以添加多个的
recyclerView.addItemDecoration(new SimpleDividerDecoration(this));
recyclerView.addItemDecoration(new LeftAndRightTagDecoration(this));
比如上面这个,SimpleDividerDecoration 画上下分割线,设置 item 4周 magin ,
LeftAndRightTagDecoration 画标签
More