View-based ItemDecoration in recyclerview

In my RecyclerView , I have several types of types, and I want to add ItemDecoration depending on the type of views. Is there any way to do this?

This will add decoration to each element:

 recyclerView.addItemDecoration(decoration); 

I saw this library , but it only supports the LinearLayoutManager vertically or horizontally, but I use GrildLayoutManager and I use drawables for delimiters.

+5
source share
2 answers

Yes, you can.

If you draw the decoration yourself, you can distinguish between different types of views in getItemOffsets and onDraw , referring to the same method on the adapter, like this:

 // 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 selected species. Having access to getLeft() and getRight() , this code supports GridLayout , as well as LinearLayout , in order to support horizontal alignment, the drawing should be done on the right side, using the same approach.

In the end, you will create a jewelry similar to 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 that will not draw before or after the headers or at the very end.

+12
source

Based on @David MedenJak's answer, I made my own item decorator for different types of views as a delay in the answer in one condition, when it draws a decorator over a section if it comes after any normal line,

  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 - this is the type of your normal string view (except for the header) call this in the next manager

  mRecyclerview.addItemDecoration(new HeaderSimpleDividerDecoration(context, 2dp , R.color.view_profile_edit_view)); 
+1
source

Source: https://habr.com/ru/post/1241486/


All Articles