2

問題概要アンドロイドRecyclerViewスイッチングレイアウト(グリッド/リスト)古いviewHolders私はリストとグリッドレイアウト間RecyclerViewを切り替えるために使用されるアクションバーボタンで活性RecyclerViewリストを持つ

使用しました。

リストをLISTおよびGRIDとして表示すると、項目のレイアウトが異なります。

リスト内の項目を表示しているときに、行フォーマットが

|----| 
|icon| Item Name 
|----| 

グリッド内のアイテムを表示する場合、行フォーマットはしたがって、私は

I参照リストとして私のリストを表示

|--------------| 
| large icon | 
|    | 
|    | 
|    |  
|--------------| 
    Item Name 

あります

|----| 
|icon| Item1 
|----| 
|----| 
|icon| Item2 
|----| 
|----| 
|icon| Item3 
|----| 
|----| 
|icon| Item3 
|----| 

と私のリストをGRIDとして表示する場合

を参照してください。
|--------------| |--------------| 
| large icon | | large icon |  
|    | |    |  
|    | |    |  
|    | |    |  
|--------------| |--------------| 
    Item1    Item2 
|--------------| |--------------| 
| large icon | | large icon | 
|    | |    | 
|    | |    | 
|    | |    |  
|--------------| |--------------| 
    Item3    Item4 

リストビューをLISTからGRIDまたはGRIDからLISTに切り替えるときに、一部のビューは他のスタイルのレイアウトでレンダリングされます。私は、切り替える前にあなたが見えないところからスクロールしたビューは再作成されるのではなく、リサイクルされ再利用されると信じています。私はリストにGRIDから行く場合

は、例えば、私は2つのレイアウトマネージャを持つ

    |--------------| 
        | large icon |  
|----|    |    |  
|icon| Item1  |    |  
|----|    |    |  
        |--------------| 
         Item2 
|--------------| |--------------| 
| large icon | | large icon | 
|    | |    | 
|    | |    | 
|    | |    |  
|--------------| |--------------| 
    Item3    Item4 

背景コード情報

を参照してください。各レイアウトスタイルのための1

private RecyclerView.LayoutManager linearLayoutManager; 
private RecyclerView.LayoutManager gridLayoutManager; 
私はグリッドとしてリストを表示していますかどうかを保存するアダプタで

またはリスト

enum ListViewEnum{ 
    LIST, 
    GRID 
} 

ListViewEnum listViewStyle = ListViewEnum.LIST; 

public ListViewEnum getListStyle() { 
    return listViewStyle; 
} 

リスト内の項目のレイアウトは、リストがされているかどうかによって異なりますリストまたはグリッドとしてレンダリングされます。

ViewHolderList 
ViewHolderGrid 

ビューホルダーを作成するとき、私はアダプタのリストビュースタイルで表示ホルダーのタイプをベース

protected RecyclerView.ViewHolder getItemViewHolder(ViewGroup parent){ 
    if (listViewStyle == ListViewEnum.LIST){ 
     View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_row, parent, false); 
     return new ViewHolderList(itemView, ....); 
    } else { 
     View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_row, parent, false); 
     return new ViewHolderGrid(itemView, ....); 
    } 
} 

ユーザーは、私は、アダプタの値

getListAdapter().setListViewMode(ListViewMode.LIST); 
を切り替えるアクションバーのボタンをクリックすると

次に更新します

listView.setLayoutManager(getListAdapter().getListStyle() == ListViewEnum.LIST ? linearLayoutManager : gridLayoutManager); 
getListAdapter().notifyDataSetChanged(); 
listView.invalidateItemDecorations(); 
invalidateOptionsMenu(); 

私はリストアダプターをリフレッシュしていますが、recycledViewsは使用できません。デバッグでは、トグルボタンをクリックすると、いくつかの位置(リサイクルされたもの)と "onCreateViewHolder"と "onBindViewHolder"(新しいもの)の呼び出しだけが表示され、古いビューホルダーがリサイクルされていることがわかります。

誤ったリストスタイルからViewHoldersを再利用しないようにリストを更新するにはどうすればよいですか?

+0

、<==>それはviewtypes' '異なるとの区別のカスタム方法を使用して、あなたの要件 – OBX

+0

代わりのを妨げない代わりにrecyclerviewの'をしてみてくださいgetItemViewType() 'ビューのレイアウト中に、同じ関数呼び出しを使用してアイテムのビュータイプが変更されているかどうかを確認するチェックがあることは確かです。これにより、すべてのビューに対して即座に 'onCreateViewHolder()'が実行されます。 – Abbas

+0

Abbas - 素晴らしく、それは完璧に働きました。そして、あなたは、ビュータイプを使用することがこれについて正しい方法であることが完全に理にかなっていることを示唆した後、提案と非常に迅速な返信をありがとうございました。 – se22as

答えて

2

@Abbasからのコメントは正しいです、getItemViewType()はおそらくあなたの最良の賭けです。あなたのデータによっては、1人の持ち主から離れてしまうこともありますが、データ項目が異なる場合は2つ作成する必要があります。表示する項目を決定するには、アダプター内のgetItemViewType()呼び出しを使用します。アダプターにアクティビティーからフラグを渡すか、アクティビティーにコールバックしてタイプを取得する必要があります。優れたUXをTabbedLayoutを作成して、二つのフラグメントのための2つRecyclerViewを作成することです

public static final int SMALL_VIEW = 0; 
public static final int LARGE_VIEW = 1; 
private int mType = 0; 

@Override 
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View v; 
     RecyclerView.ViewHolder viewHolder = null; 

     // Create the Holders depending on the type, the view type 
     // will come from the getItemViewType() call. 

     switch (viewType) { 
      case SMALL_VIEW: 
       v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_row, parent, false); 
       viewHolder = new ViewHolderList(mContext, v); 
       break; 

      case LARGE_VIEW: 
       v = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_row, parent, false); 

       viewHolder = new ViewHolderGrid(mContext, v); 
      default: 

     } 
     return viewHolder; 
    } 

    @Override 
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 

     // This switch may not be necessary if you are using 
     // the same holder for both items. 
     switch (getItemViewType(position)) { 
      case SMALL_ITEM: 
       ViewHolderList list = (ViewHolderList)holder; 
       list.setData(mData.get(position)); 
       break; 
      case LARGE_ITEM: 
       ViewHolderGrid grid = (ViewHolderGrid)holder; 
       grid.setData(mData.get(position)); 
     } 
    } 

    @Override 
    public int getItemViewType(int position) { 
     // Normally you identify the data type at position and 
     // switch the view, for your application you can switch 
     // for all. 
     return mType; 
    } 

    public void setViewType(int type) { 
     mType = type; 
    } 
+0

はい私はあなたとアッバスの提案に行った。残念なことに、アッバスのコメントとしてのコメントとして、私は彼とあなたのことを解決策としてマークすることはできません。 私は現在ビューの種類を使用しており、完全に動作します。両方とも非常にありがとう/ – se22as

1

RecyclerViews Memory Managementのおかげで、RecyclerViewはビューを再利用してスクロールを高速化しようとします。私は1つではなく2つのアダプター・インスタンスを使用して、選択されたアダプターを使用してリサイクラーを再充填すると助けになると思います。

+0

これも機能します。あまりにも複雑でないなら、私は2つのアダプターを考えています。 –

関連する問題