ItemDecoration基于recyclerview中的viewtype

时间:2016-01-26 11:59:44

标签: java android android-recyclerview

我的RecyclerView中有多个视图类型,我想根据视图类型添加ItemDecoration。有没有办法做到这一点?

这将为每个元素添加装饰:

recyclerView.addItemDecoration(decoration);

我看到了这个library,但它只支持LinearLayoutManager垂直或水平,但我使用GrildLayoutManager并且我使用drawables作为分隔符。

4 个答案:

答案 0 :(得分:20)

是的,你可以。

如果您自己绘制装饰,可以通过在适配器上访问相同的方法来区分getItemOffsetsonDraw中的不同视图类型:

// get the position
int position = parent.getChildAdapterPosition(view);
// get the view type
int viewType = parent.getAdapter().getItemViewType(position);

使用此功能,您只能为所选视图绘制装饰。通过访问代码支持getLeft()以及getRight()的{​​{1}}和GridLayout来支持水平对齐,必须完成绘图右侧使用相同的方法。

最后,您将创建如下装饰:

LinearLayout

有一个类似的sample on GitHub带有一个演示项目,它不会在标题视图之前或之后或最后绘制。

答案 1 :(得分:2)

根据@David MedenJak的回答,我为不同的视图类型创建了自己的Item Decorator,因为它在上面的部分绘制装饰器,如果它出现在任何正常的行之后,在一个条件中的答案滞后,

    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是普通行的视图类型(标题除外) 请在以下经理中致电上述内容,

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

答案 2 :(得分:0)

嗨!

基于项目视图类型对水平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)
}

有关ItemSeparator的更多信息,Here是我写来解释如何构建自己的自定义ItemDecoration的文章。

答案 3 :(得分:0)

这里有一个较短的代码,用于为某些视图类型绘制分隔线,可以轻松地将其包含在活动/片段类中:

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);
                }
            }
        }
    });