web-dev-qa-db-ja.com

RecyclerViewのビューを現在のアイテムにのみ動的に追加する

RecyclerViewのアイテムにビューを動的に追加しています。これらの追加されたビューは、それらが追加されたアイテムにのみ関連しているはずですが、スクロールすると問題が発生します。 Viewがリサイクルされ、新しいアイテムが読み込まれたようですが、以前に追加されたビューは引き続き存在し、間違ったアイテムにのみ表示されます。

ViewHolderが再利用されているからだと思います。そのため、追加されたアイテムは、ロードされると新しいアイテムとともに再び表示されます。

これをどのように解決しますか?

16
Orbit

これは私の古い質問でした。賞金がそれに置かれたので、人気の急上昇と複数の新しくて無関係な答えがありました。

この回答 への私のコメントと@ CQMの私の元の質問の下のコメントの両方で述べられているように、答えはオーバーライドすることですonViewRecycled()メソッドを実行し、そこで必要な操作を実行します。このメソッドは、ビューがリサイクルされるときに呼び出され、ここで任意のクリーンアップ操作を実行できます。

このメソッドに関するドキュメントは ここ にあります。

私の場合、ビューに添付されている非表示のTextViewを削除するだけでした。テキスト自体は削除されましたが、ビューは残りました。多くの非表示のTextViewがビューに蓄積され、スクロール時に適切にリサイクルされない場合、スクロールは遅れ始めます。

5
Orbit

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

4
Brucelet

これに基づいて:

しかし、以前に追加されたビューはまだそこにありますが、現在は間違ったアイテムにあります。

基本的に、 RecyclerView のドキュメントに従って、onBindViewHolder()メソッド内で毎回ビューをリセットする必要があります。

たとえば、プロファイルの場合にview paramを設定するメソッドがあるとすると、同じコードは次のようになります。

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

つまり、ここで行っているのは、リサイクルされたViewHolderにリセットの機会を与えることです。ヘルプが必要な場合はコメントしてください!

4
MadScientist

これが使えます! setItemViewCacheSize(int size)ここをチェック RecyclerViewDocumentation

オフスクリーンビューキャッシュは、接続されたアダプターの変更を常に認識しているため、LayoutManagerは、アダプターに戻って再バインドすることなく、これらのビューを変更せずに再利用できます。

4
Ashwin Mothilal

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 

たとえば、いくつかの可能なviewTypeがわかっている場合は、常にImageViewとTextViewになるので、いくつかのifステートメントを使用すれば問題ありません。

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

幸運を

1
Elias Fazel

子アイテムのレイアウトLinearlayoutXMLのような空のレイアウトを取得し、スクロールするときにこの方法で特定のアイテムのLinearLayoutにビューを追加する必要があります。 LinearLayoutに追加した子ビューも、そのアイテムとともにスクロールします。

0
Chetan Joshi

recyclerViewのアダプタクラスで、onBindViewHolderメソッドで、別のアダプタを作成し、新しいアダプタに対して同じメソッドを実行します。

階層は、

mainRecyclerView-> item1(-> childRecyclerView1)、item2(-> childRecyclerView2)、item3(-> childRecyclerView3)

このようにして、間違った値が間違ったアイテムに表示されることなく、必要なことを達成できます。

0
saDashiv sinha