Как обрабатывать расширяемые ViewHolders в RecyclerView? - PullRequest
0 голосов
/ 05 апреля 2019

В моем приложении RecyclerView работает с FirestoreRecyclerAdapter. В ViewHolders реализовано расширяемое меню «быстрых действий», которое расширяется при нажатии на элемент, и идеальным поведением является расширение только одного элемента за раз. Развертывание одного элемента должно свернуть все остальные элементы в адаптере.

Когда на экране достаточно предметов, чтобы разместить их все, это работает отлично. Но если список расширяется за пределы экрана, когда я пытаюсь перебрать элементы адаптера, я получаю NullPointerException, когда отсоединенные или неэкранные ViewHolders пытаются вызвать getParent().

Как я могу перебрать все 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);
    }

}

Заранее спасибо!

РЕДАКТИРОВАТЬ: Как указал Гилберто , это очень дорого. Пошел с версией решения 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());
    });

}

Ответы [ 3 ]

0 голосов
/ 06 апреля 2019

Вы не должны повторять все представления.Вам нужно просто сохранить индекс расширенного просмотра и вызвать notifyDataSetChanged или notifyItemChanged.

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 голосов
/ 06 апреля 2019

Решается путем итерации по i < recyclerView.getChildCount() и очистки VH в onViewRecycled(ViewHolder holder):

@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;
}
0 голосов
/ 06 апреля 2019

If (vh! = Null) {vh.expanded (false);}

или

Используй попробуй, лови)))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...