У меня проблема с recyclerView. Я использую этот макет для расширения cardView в recyclerView: https://github.com/AAkira/ExpandableLayout.RecyclerView каждые несколько элементов одинаковы - расширяемый элемент
Если я нажимаю на какой-либо элемент, который нужно развернуть, а затем прокрутка вниз, каждый 7-й элемент также будет расширен. Что я могу сделать, чтобы остановить этот эффект? Я знаю, что это вызвано beacause recyclerView запоминает состояние держателя вида и mIsViewExpanded в методе onBindiewHolder устанавливается равным true для каждого 7-го элемента. Заранее благодарим за любые решения!
Вот код моего viewholder:
class EventsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ImageView edit, cancel, expandIcon;
private ExpandableLayout expandableArea;
private boolean mIsViewExpanded = false;
public EventsViewHolder(View itemView) {
super(itemView);
expandIcon = (ImageView) itemView.findViewById(R.id.card_item_expand_icon);
expandIcon.setOnClickListener(this);
//divider = (View) itemView.findViewById(R.id.event_card_divider);
}
private void collapseArea(){
expandableArea.collapse();
edit.setVisibility(View.GONE);
cancel.setVisibility(View.GONE);
mIsViewExpanded = false;
expandIcon.setImageResource(R.drawable.vector_drawable_ic_expand_more_black___px);
}
private void expandArea(){
expandableArea.expand();
edit.setVisibility(View.VISIBLE);
cancel.setVisibility(View.VISIBLE);
mIsViewExpanded = true;
expandIcon.setImageResource(R.drawable.vector_drawable_ic_expand_less_black___px);
}
@Override
public void onClick(View view) {
if(mIsViewExpanded){
collapseArea();
isItemExpanded[getAdapterPosition()] = false;
}
else {
expandArea();
isItemExpanded[getAdapterPosition()] = true;
}
}
}
При нажатии на иконку внутри CardView expandableArea расширяется или разрушения в зависимости от значения mIsViewExpanded.
EDIT. Adapter Код:
public class EventsRecyclerViewAdapter extends RecyclerView.Adapter<EventsRecyclerViewAdapter.EventsViewHolder> implements PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
public interface EventsRecyclerViewAdapterInterface {
public void emptyAdapter();
public void itemDeleted(int id);
}
private List<Event> listData = new ArrayList<>();
private LayoutInflater inflater;
private MainActivity context;
private View view;
private int positionToCancel;
private boolean[] isItemExpanded;
private EventsRecyclerViewAdapterInterface deleteListener;
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
removeItem(positionToCancel);
return true;
}
@Override
public void onDismiss(PopupMenu menu) {
menu.dismiss();
}
public EventsRecyclerViewAdapter(Activity context, EventsRecyclerViewAdapterInterface deleteListener) {
this.inflater = LayoutInflater.from(context);
this.context = (MainActivity) context;
this.deleteListener = deleteListener;
}
@Override
public EventsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
view = inflater.inflate(R.layout.item_event_card, parent, false);
return new EventsViewHolder(view);
}
@Override
public void onBindViewHolder(EventsViewHolder holder, int position) {
Event item = listData.get(position);
if(!isItemExpanded[position]){
if(holder.mIsViewExpanded){
holder.collapseArea();
}
}
else {
holder.expandArea();
}
holder.title.setText(item.getName());
holder.place.setText(item.getLocation());
DateTimeFormatter formatter = DateTimeFormat.forPattern(StaticValues.DATE_TIME_PATTERN_FOR_VIEW);
holder.time.setText(formatter.print(item.getDate()));
holder.edit.setOnClickListener(view1 -> takeDetailsEvent(item));
holder.cancel.setOnClickListener(view1 -> {
positionToCancel = position;
MyPopupMenu popup = new MyPopupMenu(view1.getContext(), view1, context);
popup.inflate(R.menu.event_delete_menu);
popup.setOnMenuItemClickListener(this);
popup.setOnDismissListener(this);
popup.show();
});
holder.container.setOnClickListener(view1 -> {
Intent intent = new Intent(view1.getContext(), EventDetailsActivity.class);
intent.putExtra("eventId", item.getApiId());
view1.getContext().startActivity(intent);
});
}
private void removeItem(int position) {
deleteListener.itemDeleted(listData.get(position).getApiId());
listData.remove(position);
notifyDataSetChanged();
if (getItemCount() == 0) {
deleteListener.emptyAdapter();
}
}
private void takeDetailsEvent(Event event) {
Intent intent = new Intent(view.getContext(), CreateEventActivity.class);
intent.putExtra("id", event.getApiId());
view.getContext().startActivity(intent);
}
public void setListData(List<Event> eventList) {
listData = eventList;
isItemExpanded = new boolean[listData.size()];
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return listData.size();
}
}
Это, как я справляюсь с ним прямо сейчас. В классе адаптера у меня есть логический массив, длина которого совпадает с именем listData. В позиции, соответствующей элементу списка, я сохраняю значение: true при расширении, false при свертывании. В onBindViewHolder я проверяю, расширена ли позиция, и если я ее не срублю. Это не идеальное решение, потому что во время прокрутки элементы рушится, и это выглядит не очень хорошо.
где класс адаптера? – Rahul
В onBindViewHolder, в вашем адаптере, вы можете стандартно сжимать ViewHolder, к которому вы привязываетесь. Таким образом, все новые представления рушится. – Marcel50506
Элементы переработаны. Представления так часто, как вы прокручиваете действие по определенному элементу, повторяются для других элементов далее вверх или вниз по списку. Что вы можете сделать, это сохранить действие для элемента, использующего (.setTag()), и удалить его с помощью (.getTag()). Тогда его просто случай (если item.getTag() == 1 - Expand else Dont expand) проверьте SO о наборе и получите тег для элементов адаптера – Tasos