2015-12-31 17 views
15

私は、アイテムをRecyclerViewに動的に追加しています。これらの追加されたビューは、追加されたアイテムにのみ関連している必要がありますが、スクロールするときに問題があります。 Viewがリサイクルされ、新しいアイテムが読み込まれたようですが、以前に追加されたビューはまだそこにあります。間違ったアイテムにしか表示されません。RecyclerViewのビューを現在のアイテムのみに動的に追加する

ViewHolderが再利用されていることを前提としています。追加されたアイテムは、読み込まれると新しいアイテムで再び表示されます。

これを解決するにはどうすればよいですか?

+0

あなたのアダプタークラスコードを共有してください –

+0

リサイクルビューにアイテムを動的に追加したり、新しいビューを追加したり、データを動的に追加したりしていますか? –

+0

@CQM上記のコメントに関する回答はありますか? –

答えて

3

これは私の古い質問でした。恩恵はその上に置かれたので、人気の高まりと複数の新しい無関係な答え。

私の元の質問以下 this answer@CQMさんのコメントに、両方の私のコメントで述べたように

は、答えがonViewRecycled()メソッドをオーバーライドして、そこに必要なすべての操作を行うことです。このメソッドは、ビューがリサイクルされたときに呼び出され、ここでクリーンアップ操作を実行できます。

この方法についてのドキュメントはhereです。

私の場合、ビューに添付されている不可視のTextViewを削除することが問題でした。テキスト自体は削除されましたが、ビューはそのまま残りました。多くの目に見えないTextViewがビューに蓄積され、スクロール時に適切にリサイクルされない場合、スクロールは遅れを開始します。

3

バッキングデータに基づいて追加されたビューを追跡する必要があります。私はおそらくonBindViewHolder()に必要な追加のビューを追加し、onViewRecycled()に存在するかもしれないものを削除します。次に、動的に表示させる場合は、表示する必要がある変数を変更し、notifyItemChanged()を呼び出します。

+1

私は 'onViewRecycled'を実装しました。現在、新しいビューを追加するレイアウト内のすべての子レイアウトをループしています。削除する必要があるビューのタイプであれば' instanceof'でチェックして削除しますもしそうなら。ビューグループからすべてのタイプのビューを削除する簡単な方法はありますか?また、あなたの最後の文が何を意味していたのかは分かりません。私は現在、新しいビューのデータが自分のデータリストに含まれているので、 'onBindViewHolder'に新しいビューを追加しています。それらを動的に追加するだけで、ビューの可視性を切り替えることはできません。 – Orbit

1

Add newView操作が実行されるたびに、新しい子を持つ項目の情報をタグで保存します。 (共有設定など) タグ:onBindViewHolderのアイテム位置で作成します。

... 
SharedPreference sharedPref = getSharedPreference("text" + position, context); 
SharedPreference.Editor editor = sharedPref.edit(); 
editor.putString("view", "ImageView"); 
... 

ロードアダプターがこの値を取得し、デフォルト値をnullに設定した場合。 効率についてはわかりませんが、私はうまくいきます。

... 
String viewType = sharedPref.getString("view", null); 
//it will return ImageView 

あなたが例えば、いくつかの可能なviewTypesは常に、それはOKになりますいくつかのif文となるようImageViewの&のTextViewになるだろう知っていれば。

if(viewType.equals("ImageVIew")){ 
item(position).addView(new ImageVIew(context)); 
} 

グッドラック

+0

これを行わないでください。スクロールすると、共有環境設定にアクセスして保存することができます。 – Orbit

3

これに基づき:

が、それらの前に追加したビューはまだそこにあるが、今、間違ったアイテムに。 RecyclerViewドキュメントごとに、あなたがonBindViewHolder()メソッドの内部で毎回ビューをリセットする必要が基本的に

ので、あなたがそのあなたのプロフィール場合ビューのparamを設定する方法を持っている、としましょうしたがって、同じコードは次のようになります。

if (list.get(position).getId()==PreferenceManager.getUserID()) 
{ 
    // do some view change here 
setViewParam(true); 
}else 
{ 
    // reset the view change here 
setViewParam(false); 
} 

ここで行っていることは、再利用されたViewHolderにリセットするチャンスを与えることです。 ヘルプが必要な場合はコメントをお寄せください。あなたのrecyclerViewのあなたのアダプタクラスで

0

onBindViewHolder方法で 、 別のアダプタを作成し、新しいアダプタの同じメソッドを実行します。

階層はなり

mainRecyclerView - > ITEM1( - > childRecyclerView1)、ITEM2( - > childRecyclerView2)、ITEM3( - > childRecyclerView3)

あなたは何を達成することができますこの方法間違った値で間違った項目を表示する必要はありません。

4

これを使用できます。 setItemViewCacheSize(int size) ここをクリックRecyclerViewDocumentation

オフスクリーンビューキャッシュは、接続されたアダプタの変更を認識したままで、LayoutManagerがそれらのビューを変更せずに再利用して、それらを再バインドする必要はありません。

0

あなたがリストをスクロールすると、このようにあなたの特定の項目のLinearLayoutにビューを追加し、あなたの子供の項目のレイアウトXMLLinearlayoutのような任意の空のレイアウトを取るべきであり、あなたもLinearLayoutに追加したあなたの子ビューのすべてその項目でスクロールします。

1

まず、もっとコードを共有できますか?

第2に、なぜあなたは動的に新しいビューを動的に追加したいですか?異なるVIEWTYPEを使用したり、それらのビューをレイアウト上に表示して、それらを表示/非表示、表示/非表示にするのはなぜですか? (私はそれがこのように効率的になると信じています)。

RecyclerViewについてユーザーに思い出させてください。ユーザーがviewHolderをスクロールしているときに再利用しています(ほとんどの場合、画面いっぱいにする必要があります)。したがって、「アイテムA」のビューを追加してユーザーが「アイテムZ」にスクロールした場合、その「アイテムZ」に対してviewHolderを再利用できるため、以前に追加されたビューが表示されます。

どうすれば解決できますか?

新しいビューを追加する必要がある場合は常にすべての項目をチェックします。まだ追加されていない場合は追加します。存在しない場合は常にビューを削除してデフォルトのviewHolder状態に戻します。

希望すると、これが役立ちます。

関連する問題