私の貧しい私の英語のため申し訳ありません。RecyclerViewのスクロール正確な位置を保存して復元する方法は?
正確な位置が欲しいです。そしてまた、それは破壊されているよう同じ位置としてRecyclerView
ができ、は(私はそれを破壊したり、システムがそれを破壊に関係なく)を破壊されている活動/フラグメントの後、私は活動/フラグメントを再度開きます。
「同じ」は、項目が最後に部分的に表示されている可能性があるため、「項目の位置」を意味しません。
正確に同じ位置に復元します。
私は以下のいくつかの方法を試しましたが、誰も完璧ではありません。
誰かが役に立ちますか?
1.最初の方法。
スクロールの正確な位置を計算するのにonScrolled
を使用します。スクロールを停止して位置を保存します。 スピナーのデータセットまたはのフラグメントonCreatを変更する場合は、選択したデータセットの位置を復元します。多くの行が多数ある場合があります。
アプリが破棄された後に保存して復元することはできますが、多すぎるかもしれません。
それは
Skipped 60 frames! The application may be doing too much work on its main thread. attempt to finish an input event but the input event receiver has already been disposed. android total arena pages for jit.
が発生し、scrollY
は、フラグメントオープン、RecyclerViewは、最初のリストは、最初の項目から始まり、いくつかの遅延の後に、それがスクロール表示されます111111
、のような、巨大である場合scrollY
の位置に移動します。
これを行う方法はありますか?
recyclerView.addOnScrollListener(new OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, final int dy) {
super.onScrolled(recyclerView, dx, dy);
handler.post(new Runnable() {
@Override
public void run() {
if (isTableSwitched) {
scrollY = 0;
isTableSwitched = false;
}
scrollY = scrollY + dy;
Log.i("dy——scrollY——table", String.valueOf(dy) + "——" + String.valueOf(scrollY) + tableName);
}
});
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE:
saveRecyclerPosition(tableName, scrollY);
break;
case RecyclerView.SCROLL_STATE_DRAGGING:
break;
case RecyclerView.SCROLL_STATE_SETTLING:
break;
}
}
});
public void saveRecyclerPosition(String tableName, int y) {
prefEditorSettings.putInt(KEY_SCROLL_Y + tableName, y);
prefEditorSettings.commit();
}
public void restoreRecyclerViewState(final String tableName) {
handler.post(new Runnable() {
@Override
public void run() {
recyclerView.scrollBy(0, prefSettings.getInt(KEY_SCROLL_Y + tableName, 0));
}
});
}
//use Spinner to choose dataset
spnWordbook.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
isTableSwitched = true;
tableName= parent.getItemAtPosition(position).toString();
prefEditorSettings.putString(KEY_SPINNER_SELECTED_TABLENAME, tableName);
prefEditorSettings.commit();
wordsList = WordsManager.getWordsList(tableName);
wordCardAdapter.updateList(wordsList);
restoreRecyclerViewState(tableName);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
2.Second方法。
これは完全に実行されますが、フラグメントライフサイクルでのみ機能します。
とObjectInputStream
を使用して、HashMap
を保存して復元しようとしましたが、機能しません。
メモリに保存するにはどうすればよいですか?
private HashMap <String, Parcelable> hmRecyclerViewState = new HashMap<String, Parcelable>();
public void saveRecyclerPosition(String tableName) {
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();
hmRecyclerViewState.put(tableName, recyclerViewState);
}
public void restoreRecyclerViewState(final String tableName) {
if (hmRecyclerViewState.get(tableName) != null) {
recyclerViewState = hmRecyclerViewState.get(tableName);
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
recyclerViewState = null;
}
3.Third方法。
私が代わりにHashMap
のBundle
を使用し、第二の方法を変更するが、それは同じ質問を持っているが、フラグメントのライフサイクルのうちのときは動作しません。
私はを使用してメモリにbundle
を保存しますが、復元すると有効なbundle
が得られません。
============================================== ========================= ソリューション
みんなありがとう!
最後に、私はこの問題を解決するため、あなただけのこれらの2つの方法を参照してください、my codeでそれを見ることができます。saveRecyclerViewPositionとrestoreWordRecyclerViewPosition。
おそらく、最初に表示されたアイテムIDとそのオフセットをlayoutmanagerから取得するだけで、再作成時にその位置に移動し、スクロールをオフセットだけ調整することができます。その間にデータセットが変更された場合は、これもおそらく動作します。 –
@ bleeding182ありがとう。私もこのように考えましたが、アイテムのオフセットを取得する方法はわかりません。すべての項目は、あなただけのレイアウトマネージャからの眺めを得ることができます異なる高 – DawnYu
があり、その後、getTop()またはgetDecoratedTop()、それとの違いを読んrecyclerview.topになりますあなたのオフセット;) をそして、あなたが得るいけない場合でも、オフセットフレームをスキップせずに、適切な位置に置くことができます –