2016-08-23 43 views
3

我有一個recyclerView的問題。我正在使用此佈局來擴展recyclerView中的cardView:https://github.com/AAkira/ExpandableLayoutRecyclerView每隔幾個項目是相同的 - 擴展項

如果我點擊某個項目進行展開並且向下滾動,則每第7個元素也會展開。我能做些什麼來阻止這種影響?我知道這是由於recyclerView記住了視圖持有者的狀態並且mIsViewExpanded方法在每個第7項的BindiewHolder設置爲true時造成的。預先感謝任何解決方案!

這裏是我的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價值崩潰。

編輯。 適配器代碼:

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中,我檢查位置是否展開,如果沒有,我摺疊它。這不是理想的解決方案,因爲在滾動項目崩潰時,它看起來不太好。

+0

其中是適配器類? – Rahul

+0

在onBindViewHolder中,在您的適配器中,您可以標準摺疊您綁定的ViewHolder。這樣,所有新視圖都會崩潰。 – Marcel50506

+1

這些項目被回收視圖,因此每當您滾動對特定項目的操作時,都會重複其他項目進一步向上或向下列表。你可以做的是使用(.setTag())存儲一個項目的動作,並使用(.getTag())進行回放。然後它只是一個例子(如item.getTag()== 1 - 展開其他不擴大)檢查關於設置的SO,並獲得適配器項目的標籤 – Tasos

回答

2

RecyclerView不會創建新視圖,而是在滾動時重新使用現有視圖(ScrappedViews)。所以當你擴展CardView並滾動時,發生了什麼事情,因爲CardView被重用,所以你會得到另一個擴展視圖。

因此,只需摺疊/展開您的AdapteronBindView()中的視圖,因爲您需要將狀態與適配器列表中的每個項目相關聯。

要解決滾動期間展開/摺疊動畫只需setDuration(0),它允許您展開/摺疊沒有任何延遲或動畫更流暢的滾動體驗。

+0

是的我意識到這一點RecyclerView使用ScrappedViews這就是爲什麼我問我該怎麼做。我嘗試保存列表中每個項目的狀態。我製作了一個布爾數組來記住recyclerview中每個項目的狀態。但是當我滾動的時候,在滾動時崩潰的東西很奇怪。此外,當我在每次在onBindViewHolder項目中滾動查看視圖時,都會在滾動過程中崩潰,這不是理想的解決方案。 – Zygi

+0

@Zibiksior然後請在你的問題中添加你的「適配器」。 – Abbas

+0

在問題中發佈的適配器代碼 – Zygi

0

它是recyclerView的預期行爲。 RecyclerView回收不可見的項目。如果您不希望您的物品被回收,請使用holder.setIsRecyclable(false);在你的適配器的onBindViewHolder()方法中。

holder.setIsRecyclable(false); 
+0

使用此解決方案時的性能如何? – Zygi

+0

在這種情況下它應該像listView一樣工作。 – saty

+0

我會說這不是一個很好的解決方案,因爲@Tasos在註釋中提出的'setTag'建議可以解決問題,同時不會影響性能。 – Marcel50506