[英]ItemDecoration based on viewtype in recyclerview
I have multiple view types in my RecyclerView
and I want to add an ItemDecoration
based on the views type.我的
RecyclerView
有多种视图类型,我想根据视图类型添加一个ItemDecoration
。 Is there a way to do this?有没有办法做到这一点?
This will add a decoration to every element:这将为每个元素添加一个装饰:
recyclerView.addItemDecoration(decoration);
I saw this library but it supports only LinearLayoutManager
vertical or horizontal, but I am using GrildLayoutManager
and I use drawables for dividers.我看到了这个库,但它只支持
LinearLayoutManager
垂直或水平,但我使用的是GrildLayoutManager
并且我使用 drawables 作为分隔线。
Yes, you can.是的你可以。
If you draw the decoration yourself, you can distinguish between different view types in getItemOffsets
and onDraw
by accessing the same method on the adapter like this:如果您自己绘制装饰,您可以通过访问适配器上的相同方法来区分
getItemOffsets
和onDraw
的不同视图类型,如下所示:
// get the position
int position = parent.getChildAdapterPosition(view);
// get the view type
int viewType = parent.getAdapter().getItemViewType(position);
Using this, you can draw your decoration only for your selected views.使用它,您可以只为您选择的视图绘制装饰。 By accessing
getLeft()
and getRight()
that code supports GridLayout
as well as LinearLayout
, to support horizontal alignment, the drawing just has to be done on the right side using the same approach.通过访问代码支持
GridLayout
和LinearLayout
getLeft()
和getRight()
来支持水平对齐,只需使用相同的方法在右侧完成绘图。
In the end, you would create a decoration like the following:最后,您将创建一个如下所示的装饰:
public class DividerDecoration extends RecyclerView.ItemDecoration {
private final Paint mPaint;
private int mHeightDp;
public DividerDecoration(Context context) {
this(context, Color.argb((int) (255 * 0.2), 0, 0, 0), 1f);
}
public DividerDecoration(Context context, int color, float heightDp) {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(color);
mHeightDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, heightDp, context.getResources().getDisplayMetrics());
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
int viewType = parent.getAdapter().getItemViewType(position);
if (viewType == MY_VIEW_TYPE) {
outRect.set(0, 0, 0, mHeightDp);
} else {
outRect.setEmpty();
}
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
int viewType = parent.getAdapter().getItemViewType(position);
if (viewType == MY_VIEW_TYPE) {
c.drawRect(view.getLeft(), view.getBottom(), view.getRight(), view.getBottom() + mHeightDp, mPaint);
}
}
}
}
There is a similar sample on GitHub with a demo project, which will not draw before or after header views or at the very end. GitHub 上有一个类似的示例,带有一个演示项目,不会在标题视图之前或之后或最后绘制。
Based on @David MedenJak answer, I had made my own Item Decorator for different view types as the answer lag in one condition as it draws decorator above section, if it comes after any normal row,基于@David MedenJak 的回答,我为不同的视图类型制作了我自己的项目装饰器,因为当它在任何正常行之后绘制装饰器时,答案在一种情况下滞后,
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.ColorRes;
import android.support.annotation.DimenRes;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import java.util.Locale;
import mp.data.modal.MRecyclerListItem;
public class HeaderSimpleDividerDecoration extends RecyclerView.ItemDecoration {
private int dividerHeight;
private Paint dividerPaint;
public HeaderSimpleDividerDecoration(Context context, @DimenRes int divider_height, @ColorRes int color) {
dividerPaint = new Paint();
dividerPaint.setColor(getColor(context, color));
dividerHeight = context.getResources().getDimensionPixelSize(divider_height);
}
private int getColor(Context context, @ColorRes int drawable) {
return ContextCompat.getColor(context, drawable);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int position = parent.getChildAdapterPosition(view);
if(-1 >= position)
return;
int viewType = parent.getAdapter().getItemViewType(position);
if (MRecyclerListItem.TYPE_NORMAL == viewType) {
// outRect.set(0, 0, 0, mHeightDp);
outRect.bottom = dividerHeight;
} else
outRect.setEmpty();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
int childCount = parent.getChildCount() -1;
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int top = parent.getPaddingTop();
int bottom = parent.getHeight() - parent.getPaddingBottom();
int itemCount = parent.getAdapter().getItemCount();
for (int i = 0; i < childCount ; i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
int viewType = parent.getAdapter().getItemViewType(position);
if (MRecyclerListItem.TYPE_NORMAL == viewType) {
int nextItem = position + 1;
if(nextItem < itemCount)
{
int nextViewType = parent.getAdapter().getItemViewType(nextItem);
if(MRecyclerListItem.TYPE_NORMAL != nextViewType)
continue;
}
float topDraw = view.getBottom();
float bottomDraw = view.getBottom() + dividerHeight;
c.drawRect(left, topDraw, right, bottomDraw, dividerPaint);
}
}
}
}
MRecyclerListItem.TYPE_NORMAL is your view type of normal row(other than header) call the above in following manager, MRecyclerListItem.TYPE_NORMAL 是您的正常行(标题除外)的视图类型在以下管理器中调用上述内容,
mRecyclerview.addItemDecoration(new HeaderSimpleDividerDecoration(context,
2dp , R.color.view_profile_edit_view));
Here's a shorter code to draw divider for certain view type only that can be easily included in your activity/fragment class:这是一个较短的代码,用于为某些视图类型绘制分隔线,可以轻松包含在您的活动/片段类中:
recyclerView.addItemDecoration(new DividerItemDecoration(this, linearLayoutManager.getOrientation()) {
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
Drawable d = getDrawable();
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
int viewType = parent.getAdapter().getItemViewType(position);
// Draw divider only for view type 2 (can also put position here to remove for certain positions)
if(viewType == 2) {
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
int top = view.getBottom() + params.bottomMargin;
int bottom = top + d.getIntrinsicHeight();
d.setBounds(0, top, parent.getRight(), bottom);
d.draw(c);
}
}
}
});
Hy people !嗨人!
Example using 2 Drawable
separators for Horizontal ItemSeparator
based on items view type :基于项目视图类型为 Horizontal
ItemSeparator
使用 2 Drawable
分隔符的示例:
override fun getItemOffsets(...) {
parent.adapter?.let { adapter ->
val childAdapterPosition = parent.getChildAdapterPosition(view)
.let { if (it == RecyclerView.NO_POSITION) return else it }
rect.right = when (adapter.getItemViewType(childAdapterPosition)) {
YourAdapter.FIRST_ITEM_ID -> firstSeparator.intrinsicWidth
YourAdapter.SECOND_ITEM_ID -> secondSeparator.intrinsicWidth
else -> 0
}
}
}
override fun onDraw(...) {
parent.adapter?.let { adapter ->
parent.children
.forEach { view ->
val childAdapterPosition = parent.getChildAdapterPosition(view)
.let { if (it == RecyclerView.NO_POSITION) return else it }
when (adapter.getItemViewType(childAdapterPosition)) {
CustomAdapter.FIRST_ITEM_ID -> firstSeparator.draw(...)
CustomAdapter.SECOND_ITEM_ID -> secondSeparator.draw(...)
else -> Unit
}
}
}
}
private fun Drawable.draw(view: View, parent: RecyclerView, canvas: Canvas) = apply {
val left = view.right
val top = parent.paddingTop
val right = left + intrinsicWidth
val bottom = top + intrinsicHeight - parent.paddingBottom
bounds = Rect(left, top, right, bottom)
draw(canvas)
}
For more info on ItemSeparator
, Here is the article I wrote to explain how to build your own custom ItemDecoration.有关
ItemSeparator
更多信息, 这是我写的文章,用于解释如何构建您自己的自定义 ItemDecoration。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.