web-dev-qa-db-ja.com

AndroidでRecyclerViewのスクロール位置を保存する方法は?

SwipeRefreshLayout内にあるリサイクルビューがあります。また、別のアクティビティで各アイテムを開くことができます。ごみ箱に戻った後、選択したアイテム、または前のYまでスクロールする必要があります。

はい、グーグルで検索して、StackOverFlowでレイアウトマネージャーのインスタンスの保存に関する記事を見つけました。次のようなものです。 RecyclerViewストア/アクティビティ間の状態の復元 。しかし、それは私を助けません。

[〜#〜] update [〜#〜]

現在、この種の問題を解決していますが、もちろん、それも機能しません。

private int scrollPosition;

...//onViewCreated - it is fragment
recyclerView.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(llm);
data = new ArrayList<>();
adapter.setData(getActivity(), data);
recyclerView.setAdapter(adapter);
...

@Override
public void onResume() {
    super.onResume();
    recyclerView.setScrollY(scrollPosition);
}

@Override
public void onPause() {
    super.onPause();
    scrollPosition = recyclerView.getScrollY();
}

はい、scrollTo(int、int)を試しました-動作しません。

ここで、たとえばY = 100にスクロールしようとしましたが、まったくスクロールしません。

18
DefaultXYZ

リサイクルビューの位置@onPauseの現在の状態を保存します。

    positionIndex= llManager.findFirstVisibleItemPosition();
    View startView = rv.getChildAt(0);
    topView = (startView == null) ? 0 : (startView.getTop() - rv.getPaddingTop());

スクロール位置@onResumeを復元します。

    if (positionIndex!= -1) {
        llManager.scrollToPositionWithOffset(positionIndex, topView);
    }

または、別の方法は@onPauseです。

long currentVisiblePosition = 0;
currentVisiblePosition = ((LinearLayoutManager)rv.getLayoutManager()).findFirstCompletelyVisibleItemPosition();

@onResumeの復元:

((LinearLayoutManager) rv.getLayoutManager()).scrollToPosition(currentVisiblePosition);
currentVisiblePosition = 0;
40
Madhukar Hebbar

これらの答えの多くは、それを複雑にしているようです。

LayoutManagerはすぐにonRestoreInstanceStateをサポートするため、スクロール位置などを保存する必要はありません。組み込みのメソッドは既にピクセルの完全な位置を保存しています。

フラグメントコードの例(わかりやすくするためにヌルチェックなどを削除):

private Parcelable listState;
private RecyclerView list;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    listState=savedInstanceState.getParcelable("ListState");

}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putParcelable("ListState", list.getLayoutManager().onSaveInstanceState());

}

それからただ電話する

list.getLayoutManager().onRestoreInstanceState(listState);

データがRecyclerViewに再アタッチされたら

20
Kuffs

スクロール位置を取得するために、リサイクラビューのlinearlayoutmanagerを使用する

int position = 0;
if (linearLayoutManager != null) {
   scrollPosition = inearLayoutManager.findFirstVisibleItemPosition();
}

復元するときは次のコードを使用します

if (linearLayoutManager != null) {
  cardRecyclerView.scrollToPosition(mScrollPosition);
}

これがあなたを助けることを願っています

2
Nikhil

設定に位置を保存するには、これをonStop()に追加します

 int currentVisiblePosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
 getPreferences(MODE_PRIVATE).edit().putInt("listPosition", currentVisiblePosition).apply();

次に、このような位置を復元します

 if (getItemCount() == 0) {
     int savedListPosition = getPreferences(MODE_PRIVATE).getInt("listPosition", 0);
     recyclerView.getLayoutManager().scrollToPosition(savedListPosition); }

この最後のコードは、アダプターのイベント内に追加する必要があります(確実に魔女イベントではありませんが、私の場合はonEvent()-com.google.firebase.firestore.EventListener)

0
Dan Alboteanu

何らかの理由で、向きの変更時にyour_scrolling_containerでスクロール位置を保存および復元する方法について、非常に誤解を招くヒント/提案がたくさんあります。

現在のスクロール位置を取得し、アクティビティのonSaveInstanceStateに保存します。特定のスクロール可能なビューを拡張して、そこで同じことを行います。

しかし、実際には、Androidはすでにあなたのためにそれをやっているので、すべてがはるかに簡単です!

RecyclerView/ListView/ScrollView/NestedScrollViewソースを詳しく見ると、それぞれがonSaveInstanceStateにスクロール位置を保存していることがわかります。そして、最初のレイアウトパス中に、onLayoutメソッドでこの位置にスクロールしようとしています。

正常に機能することを確認するために必要なことは2つだけです。

  1. おそらく既に行われているスクロール可能なビューのIDを設定します。そうしないと、Androidはビューステートを自動的に保存できません。

  2. 最初のレイアウトパスの前にデータを提供し、回転前と同じスクロール境界を設定します。これは、開発者が通常いくつかの問題を抱えるステップです。

0
Andrey T

私が見つけた最も簡単で移行互換の方法は次のとおりです。

   @Override
public void onPause() {
    super.onPause();
    recyclerView.setLayoutFrozen(true);
}

@Override
public void onResume() {
    super.onResume();
    recyclerView.setLayoutFrozen(false);
}
0
Mikias