基于回收商视图中的视图的项装饰

2022-09-02 02:58:52

我在 my 中有多个视图类型,我想添加一个基于视图类型的视图。有没有办法做到这一点?RecyclerViewItemDecoration

这将为每个元素添加一个修饰:

recyclerView.addItemDecoration(decoration);

我看到了这个,但它只支持垂直或水平,但我使用并且我使用可绘制的分隔符。LinearLayoutManagerGrildLayoutManager


答案 1

是的,可以。

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

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

使用此功能,您可以仅为所选视图绘制装饰。通过访问和该代码支持以及,以支持水平对齐,绘图只需使用相同的方法在右侧完成即可。getLeft()getRight()GridLayoutLinearLayout

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

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

GitHub上有一个类似的示例,其中包含一个演示项目,它不会在标题视图之前或之后或最后绘制。


答案 2

基于@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是你的视图类型普通行(标题除外)调用上面的下面的管理器,

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

推荐