将视图动态添加到RecyclerView的项目

时间:2015-09-01 13:01:06

标签: android android-recyclerview

我想根据发送到TextView

的ModalObject将额外的RecyclerView.Adapter添加到RecyclerView.Adapter的项目中

示例

我有一个带有isAddText变量的模态对象。在onCreateViewHolder中,我们会创建持有者对象,并将itemView作为参数发送。

@Override
public SolventViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
    View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.solvent_list, null);
    SolventViewHolders rcv = new SolventViewHolders(layoutView);
    return rcv;
}

SolventViewHolders.java

public SolventViewHolders(View itemView) {
    super(itemView);
    itemView.setOnClickListener(this);
    textView = (TextView) itemView.findViewById(R.id.country_name);
    imageView = (ImageView) itemView.findViewById(R.id.country_photo);
    //  Now i need add a view to the itemView parent based on ModalObject isAddView property and how to do that. 
}

3 个答案:

答案 0 :(得分:23)

问题

通常,您需要执行itemView.addView(view,layoutParams)以编程方式将另一个视图添加到您的布局中,但ViewHolders的内容是,它们将被RecyclerView重用以绑定适配器中的不同项目,因此您可以&这样做,或者当另一个项目再次绑定到此viewHolder实例时,将显示您要添加的新TextView。

我可以想到一些可以实现目标的方法:

1。切换视图的可见性

第一种方法是将此textView添加到您的布局中,默认情况下通过GONE可见,并在绑定您需要此TextView的项目时将其设置为VISIBLE,例如:

@Override
public void onBindViewHolder(AbstractViewHolder holder, int position) {
    holder.extraTextView.setVisibility(View.GONE);
    if(shouldShowExtraTextView) {
        holder.extraTextView.setVisibility(View.VISIBLE);
        holder.extraTextView.setText(/* your text */);
    }
    // proceed to bind item to holder
}

2。实现不同的ViewHolders

第二种方式更优雅,它涉及创建不同的ViewHolder类型。首先,您需要为RecyclerView显示的两种类型的视图创建int常量。在适配器中放置以下代码:

private static final int VIEW_ORDINARY = 0;
private static final int VIEW_WITH_EXTRA_TEXT_VIEW = 1;

然后实现适配器的getItemViewType(int position)方法:

@Override
public int getItemViewType(int position) {
    if(position == /* position of item that needs extra text view */) {
        return VIEW_WITH_EXTRA_TEXT_VIEW;
    } else {
        return VIEW_ORDINARY;
    }
}

下一步是根据返回的类型创建不同的Holder:

@Override
public SolventViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if(viewType == VIEW_WITH_EXTRA_TEXT_VIEW) {
        View itemView = LayoutInflater.from(parent.getContext())
                                      .inflate(R.layout.solvent_list_with_extra_text_view, parent, false);
        return new SolventViewHolderWithExtraTextView(itemView);
    } else {
        View itemView = LayoutInflater.from(parent.getContext())
                                      .inflate(R.layout.solvent_list, parent, false);
        return new SolventViewHolder(itemView);
    }
}

当然你需要定义SolventViewHolderWithExtraTextView:

class SolventViewHolderWithExtraTextView extends SolventViewHolder {
    TextView extraTextView;

    public SolventViewHolderWithExtraTextView(View itemView) {
        super(itemView);
        this.extraTextView = (TextView) findViewById(R.id.extra_text_view);
    }
}

然后在onBindViewHolder():

@Override
public void onBindViewHolder(SolventViewHolder holder, int position) {
    // you can use inheritance to handle binding logic or check the item view type again:
    // bind ordinary view
    if(getItemViewType(position)) {
        // bind the extra textView
        ((SolventViewHolderWithExtraTextView)holder).extraTextView.setText("I hope this works");
    }
}

这样您就可以为需要另一个TextView的项目使用另一种类型的ViewHolder,它将在该类别中重复使用。这是做你想做的事情的首选方式。

3。添加/删除动态查看

另一个答案(如果你问我,这是非常难看的解决方案)是动态添加和删除视图,例如:

@Override
public void onBindViewHolder(AbstractViewHolder holder, int position) {
    if(shouldDisplayExtraTextView) {
        if(!holder.displaysExtraTextView() {
            holder.addExtraTextView();
        }
        holder.extraTextView.setText("This solution is really ugly");
        } else {
        if(holder.displaysExtraTextView() {
            holder.removeExtraTextView();
        }
    }
}

class SolventViewHolders extends RecyclerView.ViewHolder {
    TextView extraTextView;
    boolean viewAdded = false;

    public SolventViewHolders(View itemView) {
        super(itemView);
        itemView.setOnClickListener(this);
        textView = (TextView) itemView.findViewById(R.id.country_name);
        imageView = (ImageView) itemView.findViewById(R.id.country_photo);
         //  Now i need add a view to the itemView parent based on ModalObject isAddView property and how to do that. 

        extraTextView = new TextView();
}

public void addExtraTextView() {
    ((ViewGroup)itemView).addView(extraTextView, layoutParams);
    viewAdded = true;
}

public void removeExtraTextView() {
    ((ViewGroup)itemView).removeView(extraTextView);
    viewAdded = false;
}

public boolean displaysExtraTextView() {
    return viewAdded;
}

这非常难看,因为要向itemView添加视图,您需要将其强制转换为ViewGroup(它不必这样),因此请确保它始终是ViewGroup或其子类。此外,您需要提供正确的layoutParams以将extraTextView添加到itemView。

答案 1 :(得分:3)

您还可以设置itemView.setHasTransientState(true),在setHasTransientState设置为false之前,视图不会被回收。

答案 2 :(得分:1)

在@ grgrssll的答案的帮助下,我能够解决我的问题。在我的情况下,我需要在每行内部使用N个TextView。

在我的 onBindViewHolder

@Override
public void onBindViewHolder(@NonNull final HistoryViewHolder vh, int position) {
    ...
    //Generating N-number of TextViews depending on size of itemsMap
    for (Map.Entry<String, Model> entry : itemsMap.entrySet()) {
        SelectedModel s = entry.getValue();
        // Set setHasTransientState to true
        vh.itemDetailsContainer.setHasTransientState(true);    
        // Dynamically adding the views
        vh.itemDetailsContainer.addView(getItemTextView(context, s.getItemName()));
        ...
    }
    //Set setHasTranssientState to false after loop
    vh.itemDetailsContainer.setHasTransientState(false);
    ...
}