【问题标题】:Using ItemDecorator to make separators in a RecyclerView使用 ItemDecorator 在 RecyclerView 中制作分隔符
【发布时间】:2014-11-11 11:43:23
【问题描述】:

我正在尝试使用ItemDecorator 将一些分隔符添加到RecyclerView。这是执行此操作的代码片段。

//...
public abstract C onInflateViewHolder(Context ctx);

public abstract void onBindViewHolder(C holder, int index);

@Override
public void onDraw(Canvas c, RecyclerView parent) {
    if (mOrientation == VERTICAL_LIST) {
        drawVertical(c, parent);
    } else {
        drawHorizontal(c, parent);
    }
}

public void drawVertical(Canvas c, RecyclerView parent) {
    final int left = parent.getPaddingLeft();
    final int right = parent.getWidth() - parent.getPaddingRight();
    for (int i = 0; i < parent.getChildCount(); i++) {
        C view = onInflateViewHolder(mContext);
        onBindViewHolder(view, i);
        RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);
        //parent.addView(view.itemView, i, p);
        view.itemView.draw(c);
    }
}
//...

如您所见,我尝试使用parent.addView(view.itemView, i, p);parent.addView(view.itemView, i);,最后使用view.itemView.draw(c);

这是实现:

mItemDecorator =
                new GenericDecorator<ChatDateSeparatorViewHolder>(getActivity(), GenericDecorator.VERTICAL_LIST) {
                    @Override
                    public ChatDateSeparatorViewHolder onInflateViewHolder(Context ctx) {
                        View v = LayoutInflater.from(ctx).inflate(R.layout.chat_message_separator, null);
                        return new ChatDateSeparatorViewHolder(v);
                    }

                    @Override
                    public void onBindViewHolder(ChatDateSeparatorViewHolder holder, int index) {
                        if (index < mAdapter.getItemCount()-1) {
                            ChatMessage previous = mAdapter.getMessage(index);
                            ChatMessage current = mAdapter.getMessage(index+1);

                            long startTime = previous.getSendDate().getTime();
                            long endTime = current.getSendDate().getTime();
                            long diffTime = endTime - startTime;
                            long diffDays = diffTime / (1000 * 60 * 60 * 24);

                            if (diffDays > 0) {
                                holder.text.setText(Converters.format(current.getSendDate(), getActivity()));
                            } else {
                                holder.root.setVisibility(View.GONE);
                            }
                        } else {
                            holder.root.setVisibility(View.GONE);
                        }

                    }
        };

顺便说一句,C 是Recycler.ViewHolder,正如您在实现中看到的那样。

一切似乎都很好,但是在尝试添加视图时它会崩溃。当我将 addView 与 LayoutParams 广告 at android.support.v7.widget.RecyclerView$LayoutParams.getViewPosition(RecyclerView.java:6957) 一起使用时,我得到的例外是 NullpointerException

我只需要知道如何在不使用适配器的情况下以编程方式将View 添加到RecyclerView

编辑:

我正在尝试在RecyclerView 中添加分隔符,此分隔符将是我从ViewHolder 获得的视图,一切都已完成,我唯一需要知道的是如何以编程方式添加视图(我从我的ViewHolder 获得)到RecyclerView

这是应用程序模型的屏幕截图,因此您会有更好的想法:

写着“Hoy”(今天是西班牙语)的那一行是分隔符之一。

【问题讨论】:

  • ItemDecoration 是嗯,一个装饰,所以你为什么要这样做:view.itemView.draw(c); ?
  • 只是随机的一行代码,我试过了,因为我已经尝试过addView(View,Index)addView(View,Index,LayoutParams),我这样做只是为了试一试。
  • 添加视图?在项目装饰?为什么?你想达到什么目标?
  • 我编辑了这个问题,所以你会更好地了解发生了什么。

标签: java android draw android-recyclerview


【解决方案1】:

你可以通过使用你的物品View's标签来做到这一点

在您的Adapter's onBindViewHolder 中,您可以确定这是否是当天的最后一条消息。如果这是当天的最后一条消息,那么您可以拨打holder.itemView.setTag("isLastForDay") 之类的电话。

然后在您的装饰器中,在循环遍历您的 RecyclerView's 孩子时,读取每个孩子的标签。如果标签包含“isLastForDay”,则执行“hoy”绘图逻辑。

【讨论】:

    【解决方案2】:

    这就是我经常这样做的方式

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        recyclerView.setLayoutManager(layoutManager);
    
        RecycleMarginDecoration recycleMarginDecoration = new RecycleMarginDecoration(this);
        recyclerView.addItemDecoration(recycleMarginDecoration);
    

    添加装饰器类

    public class RecycleMarginDecoration extends RecyclerView.ItemDecoration {
    
    private int margin;
    
    public RecycleMarginDecoration(Context context) {
      /* Assign value from xml whatever you want to make as margin*/
        margin = context.getResources().getDimensionPixelSize(R.dimen.padding_four);
    }
    
    @Override
    public void getItemOffsets(
            Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.set(margin, margin / 2, margin / 2, 0);
    }
    

    }

    【讨论】:

    • 是的,但正如我在问题中所说,我的分隔符是 ViewHolders 我如何使用 ItemDecoration 和视图持有者的 xml 添加它们?
    • 好的,正如您正在讨论的那个 HOY 视图,据我所知,这也是一个添加的视图,而不是任何项目装饰器。在适配器 public int getItemViewType(int position) { if (lsItem.size() == 0) return EMPTY_VIEW; /*null Indicate Loader*/ if (lsItem.get(position) == null) return PROGRESS_VIEW; return super.getItemViewType(position); } 的 getItemViewType() 方法中定义另一种视图,这就是我在 recyclerview 中创建两种不同类型视图的方式
    • 是的,没错,一年前我就是这样解决这个问题的,但是我在等待有人能告诉我怎么做,不是在我的适配器中添加不同类型的视图而是添加带有 ItemDecorator 的视图,毕竟这不是不同类型的视图,是一个分隔符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多