web-dev-qa-db-ja.com

RecyclerView notifyDataSetChangedが最上部にスクロールする

notifyDataSetChangedRecyclerViewで呼び出すと、スクロール位置が保持されずに上にスクロールします。スクロール位置を保持する解決策はありますか?

18

RecyclerViewリストアイテムの親に「wrap_content」プロパティがある場合、Recyclerviewは高さを再度計算し、上にスクロールします。

2つの解決策があります。

  1. 次のように高さを定数値に設定します:_layout_height="100dp"_
  2. 次のようにStaggeredGridLayoutManagerを使用します。

    mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL));

2番目の解決策はより効率的であり、私はこれを提案します

15
serefakyuz

これで問題が解決するかどうかはわかりませんが、同じ問題が発生していました。通知後にsetAdapterを呼び出していたためです。したがって、通知後にsetAdapterを呼び出さないことで問題は解決しました。

mAdapter.notifyItemRangeInserted(mAdapter.getItemCount(), list.size() - 1);
recyclerView.setAdapter(); // remove this line. 
//Do this only when you're setting the data for the first time or when adapter is null. 
8
user3354265

私が推測しているように、あなたがしていることは、アダプタをRecyclerViewにリセットしてからnotifyDataSetChanged().を呼び出すことです

アダプターupdate(dataList)のようなアダプターメソッドでdataListを渡すことにより、dataListのみをアダプターに渡す必要があります。このメソッドでは、このリストを次のようにアダプタリストに割り当てることができます。

public void update(ArrayList<Hashmap<String,String> list){
  this.mList = list;
}
2
Sandy

私の場合、recyclerviewにはページ番号が付けられていました。最後に到達し、notifyItemInsertedを使用して項目をロード/挿入するたびに、recyclerViewがスクロールに使用されました。だから私のために働いた:

recycler_view.stopScroll();

ドキュメントに記載されているように:

SmoothScrollBy(int、int)、fling(int、int)、またはタッチで開始されたフリングによって開始されたスクロールなど、進行中の現在のスクロールを停止します。

1
Ritesh Karmare

RecycleViewは、レイアウトマネージャーがない場合、notifyDataSetChangedのバリアントの一番上にスクロールして戻ります。これを設定する方法の例を次に示します。

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context, OrientationHelper.VERTICAL, false);
recycleView.setLayoutManager(linearLayoutManager);
1
Maxwell

swapAdapter() を使用し、呼び出し後に notifyDataSetChange() を使用できます。これは私にとってはうまくいきます。

0
Cagdas

notifyDataSetChangedの前に保存して位置を保持し、保存された位置までスムーズスクロールを呼び出すことができます。

final int currentVisibleItem = ((LinearLayoutManager) layourmanager).findFirstCompletelyVisibleItemPosition();
                           productListAdapter.notifyDataSetChanged();
                            Handler handler = new Handler();
                            handler.postDelayed(new Runnable() {
                                @Override
                                public void run() {

                    if(currentVisibleItem>-1 && currentVisibleItem<lstProducts.size())
                                    rv_products.scrollToPosition(currentVisibleItem);
                                }
                            }, 100);
0
Rajesh Nasit