java recyclerview中基于viewtype的ItemDecoration
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35013383/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ItemDecoration based on viewtype in recyclerview
提问by user3531883
I have multiple view typesin my RecyclerView
and I want to add an ItemDecoration
based on the views type. Is there a way to do this?
我有多种视图类型,我RecyclerView
想ItemDecoration
根据视图类型添加一个。有没有办法做到这一点?
This will add a decoration to every element:
这将为每个元素添加一个装饰:
recyclerView.addItemDecoration(decoration);
I saw this librarybut it supports only LinearLayoutManager
vertical or horizontal, but I am using GrildLayoutManager
and I use drawables for dividers.
我看到了这个库,但它只支持LinearLayoutManager
垂直或水平,但我正在使用GrildLayoutManager
并且我使用 drawables 作为分隔线。
回答by David Medenjak
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 horizontalalignment, the drawing just has to be done on the right side using the same approach.
使用它,您可以只为您选择的视图绘制装饰。通过访问getLeft()
和getRight()
该代码支持GridLayout
以及LinearLayout
支持水平对齐,绘图只需使用相同的方法在右侧完成。
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 GitHubwith a demo project, which will not draw before or after header views or at the very end.
回答by Reprator
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));
回答by Nicolas Duponchel
Hy people !
嗨人!
Example using 2 Drawable
separators for Horizontal ItemSeparator
based on items view type :
基于项目视图类型Drawable
为水平使用 2 个分隔符的示例ItemSeparator
:
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
, Hereis the article I wrote to explain how to build your own custom ItemDecoration.
有关更多信息ItemSeparator
,这是我写的文章,用于解释如何构建您自己的自定义 ItemDecoration。