如何在RecyclerView中处理可扩展的ViewHolders?

问题描述 投票:0回答:3

我有一个RecyclerView在我的应用程序中使用FirestoreRecyclerAdapterViewHolders实现了一个可扩展的“快速操作”菜单,该菜单可以在点击项目时进行扩展,理想的行为是一次只扩展一个项目。扩展一个项目应该折叠适配器中的所有其他项目。

当没有足够的项目可以在屏幕上显示它们时,这很好。但是如果列表在屏幕外扩展,当我尝试迭代适配器的项目时,当分离或屏幕外的ViewHolders尝试调用NullPointerException时,我会得到一个getParent()

如何迭代适配器中的所有ViewHolders,或者只迭代可见的ViewHolders?

相关适配器代码:

@Override
protected void onBindViewHolder(@NonNull BrewViewHolder holder, 
               int position, @NonNull Brew brew) {

    // Bind Views
    holder.bind(brew);

    // Set expander ClickListener
    holder.card.setOnClickListener(v -> {
        for (int i = 0; i < mAdapter.getItemCount(); i++) {
            if (i != position) {
                // ERROR THROWN HERE
                BrewViewHolder vh = ((BrewViewHolder) recyclerView.getChildViewHolder(recyclerView.getChildAt(i)));
                vh.expanded = false;
            }
        }
        holder.expanded = !holder.expanded;
        notifyItemChanged(position);
   });

}

相关的ViewHolder代码:

public class BrewViewHolder extends RecyclerView.ViewHolder {

    // Expanded state
    public boolean expanded = false;
    ...

    public BrewViewHolder(@NonNull final View itemView) {
        super(itemView);
        ...
        // Set visibility of quick actions based on expanded state
        quickActions.setVisibility(expanded ? View.VISIBLE : View.GONE);
    }

}

提前致谢!

编辑:正如Gilberto所指出的,这是非常昂贵的。使用Andrew解决方案的版本:

private int expandedItemIndex = -1;

@Override
protected void onBindViewHolder(@NonNull BrewViewHolder holder, int position,
                                @NonNull Brew brew) {
    // Bind Views
    holder.bind(brew);

    // Set expander ClickListener
    holder.card.setOnClickListener(v -> {
        if (position == expandedItemIndex) {
            holder.expanded = false;
            expandedItemIndex = -1;
        } else {
            holder.expanded = true;
            if (expandedItemIndex != -1) {
                BrewViewHolder otherHolder = ((BrewViewHolder) recyclerView.getChildViewHolder(
                        recyclerView.getChildAt(expandedItemIndex)));
                otherHolder.expanded = false;
            }
            expandedItemIndex = position;
        }
        notifyItemRangeChanged(0, recyclerView.getChildCount());
    });

}
android android-recyclerview android-viewholder
3个回答
0
投票

您不应该迭代所有视图。您只需要保存展开视图的索引并调用notifyDataSetChangednotifyItemChanged

private int expandedItemIndex = -1;

@Override
protected void onBindViewHolder(@NonNull BrewViewHolder holder, 
               final int position, @NonNull Brew brew) {

    // Bind Views
    holder.bind(brew);

    // Set expander ClickListener
    holder.card.setOnClickListener(v -> {
        if (position == expandedItemIndex) {
            notifyItemChanged(position);
            expandedItemIndex = -1;
        } else {
            if (expandedItemIndex != -1) {
                notifyItemChanged(expandedItemIndex);
            }
            expandedItemIndex = position;
            notifyItemChanged(position);
        }
   });

   if (position == expandedItemIndex) {
      // Expand
      holder.quickActions.setVisibility(View.VISIBLE);
   } else {
      // Collapse
      holder.quickActions.setVisibility(View.GONE);
   }
}

0
投票

如果(vh!= null){vh.expanded(false);}

要么

使用try,catch)))


0
投票

通过迭代i < recyclerView.getChildCount()并确保在onViewRecycled(ViewHolder holder)中清理VH来解决:

@Override
protected void onBindViewHolder(@NonNull BrewViewHolder holder, int position, @NonNull Brew brew) {
    // Bind Views
    holder.bind(brew);

    // Set expander ClickListener
    holder.card.setOnClickListener(v -> {
        for (int i = 0; i < recyclerView.getChildCount(); i++) {
            if (i != position) {
                BrewViewHolder otherHolder = ((BrewViewHolder) recyclerView.getChildViewHolder(recyclerView.getChildAt(i)));
                otherHolder.expanded = false;
            }
        }
        holder.expanded = !holder.expanded;
        notifyItemRangeChanged(0, recyclerView.getChildCount());
    });
}

@Override
public void onViewRecycled(@NonNull BrewViewHolder holder) {
    super.onViewRecycled(holder);
    holder.expanded = false;
}
© www.soinside.com 2019 - 2024. All rights reserved.