リストビューに戻るときにスクロール位置を維持/保存/復元する


397

ListViewユーザーが前の画面に戻る前にスクロールできるのに時間がかかります。ユーザーがこれをListView再び開いたときに、リストを以前と同じポイントまでスクロールします。これを達成する方法に関するアイデアはありますか?


22
Eugene Mymrin / Giorgio Barchiesiによって言及された解決策は、受け入れられた回答より優れていると思います
Mira Weller

回答:


631

これを試して:

// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());

// ...

// restore index and position
mList.setSelectionFromTop(index, top);

説明:

ListView.getFirstVisiblePosition()上部に表示されるリストアイテムを返します。ただし、このアイテムは部分的にスクロールされて表示されない場合があり、リストの正確なスクロール位置を復元したい場合は、このオフセットを取得する必要があります。だから、ListView.getChildAt(0)返しViewのトップリストの項目は、その後View.getTop() - mList.getPaddingTop()の先頭からのオフセットの相対を返しますListView。次に、ListViewのスクロール位置を復元するために、ListView.setSelectionFromTop()必要な項目のインデックスとオフセットを使用して呼び出し、の上端をの上から配置しListViewます。


2
これがどのように機能するか本当に理解していません。私はlistView.getFirstVisiblePosition()のみを使用しており、それを理解していますが、ここで何が起こっているのかわかりません。簡単な説明がありますか?:)
HXCaine

56
したがって、ListView.getFirstVisiblePosition()は、表示されている一番上のリストアイテムを返します。ただし、このアイテムは部分的にスクロールされて表示されない場合があり、リストの正確なスクロール位置を復元したい場合は、このオフセットを取得する必要があります。そのため、ListView.getChildAt(0)は最上位のリスト項目のビューを返し、View.getTop()はListViewの最上部からの相対オフセットを返します。次に、ListViewのスクロール位置を復元するために、必要な項目のインデックスと、ListViewの上から上端を配置するためのオフセットを指定して、ListView.setSelectionFromTop()を呼び出します。すべてクリア?
イアン

15
これは、保存にint index = mList.getFirstVisiblePosition();1行、復元に1行のみを使用することで、さらに簡単にすることができますmList.setSelectionFromTop(index, 0);。すばらしい回答ですが(+1)!私はこの問題のエレガントな解決策を探していました。
Phil

17
@Philの単純化したソリューションでは、正確なスクロール位置を復元できません。
Ixx

2
@nbarrailleが言ったように、コードは「v.getTop()-mList.getPaddingTop()」のように読む必要があります。私は...それは常にちょうど髪オフを復元する理由を理解しようとしなかったようにそうしないと、時間を費やすだろう
jdowdell

544
Parcelable state;

@Override
public void onPause() {    
    // Save ListView state @ onPause
    Log.d(TAG, "saving listview state");
    state = listView.onSaveInstanceState();
    super.onPause();
}
...

@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    // Set new items
    listView.setAdapter(adapter);
    ...
    // Restore previous state (including selected item index and scroll position)
    if(state != null) {
        Log.d(TAG, "trying to restore listview state");
        listView.onRestoreInstanceState(state);
    }
}

106
この方法は最初の表示項目だけでなく正確なスクロール位置を復元するので、これが最良の答えだと思います。
Mira Weller

9
すばらしい答えですが、コンテンツを動的にロードしていて、onPause()メソッドで状態を保存したい場合は機能しません。
ジオ

13
素晴らしいソリューション。ただ一つの問題。アイテムが大きく、スクロールしても最初のアイテムが表示されている場合、リストはトップに戻ります。2番目の項目または他の場所にスクロールすると、すべてが機能します
passsy

4
@passsyリストがトップに戻る解決策を見つけたことがありますか?
Papajohn000 14年

2
aaronvargasが言ったようListView.getFirstVisiblePosition()が0である場合、これは動作しませんでした
VinceStyling

54

@(Kirk Woll)によって提案された解決策を採用しました。「連絡先」アプリのAndroidソースコードでも、同様の手法を使用していることがわかりました。さらに詳細を追加したいと思います。ListActivity派生クラスの上に:

private static final String LIST_STATE = "listState";
private Parcelable mListState = null;

次に、いくつかのメソッドがオーバーライドします。

@Override
protected void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);
    mListState = state.getParcelable(LIST_STATE);
}

@Override
protected void onResume() {
    super.onResume();
    loadData();
    if (mListState != null)
        getListView().onRestoreInstanceState(mListState);
    mListState = null;
}

@Override
protected void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);
    mListState = getListView().onSaveInstanceState();
    state.putParcelable(LIST_STATE, mListState);
}

もちろん、「loadData」は、DBからデータを取得してリストに配置するための関数です。

私のFroyoデバイスでは、これは電話の向きを変更したときと、アイテムを編集してリストに戻ったときの両方で機能します。


1
この解決策は私にとってうまくいきました。他の人はしませんでした。ListViewのアイテムの削除と挿入に関して、ListViewインスタンスの状態の保存/復元はどのように機能しますか?
ブライアン

2
ちなみに、これをフラグメントで使用していて(リストフラグメントを使用している)、他のフラグメントに移動すると、mListState = getListView().onSaveInstanceState().主にデバイスのローテーションで呼び出すときにコンテンツビューが作成されないため、クラッシュします。
Mgamerz 2014

2
onRestoreInstanceState 呼び出されることは決してない:(
dVaffection

1
@GiorgioBarchiesi解決策が機能する@(Kirk Wool)は誰ですか?ユーザーが名前を変更したようです。
ピオベザン

1
はい、それは公式の宗教です。しかし、私の場合、データはローカルに読み込まれ、長さが非常に制限されており、1秒で読み込まれます。そのため、私は正直に行きました:-)
Giorgio Barchiesi

26

非常に簡単な方法:

/** Save the position **/
int currentPosition = listView.getFirstVisiblePosition();

//Here u should save the currentPosition anywhere

/** Restore the previus saved position **/
listView.setSelection(savedPosition);

メソッドsetSelectionは、リストを提供されたアイテムにリセットします。タッチモードでない場合、アイテムは実際に選択されます。タッチモードの場合、アイテムは画面上にのみ配置されます。

より複雑なアプローチ:

listView.setOnScrollListener(this);

//Implements the interface:
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
    mCurrentX = view.getScrollX();
    mCurrentY = view.getScrollY();
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {

}

//Save anywere the x and the y

/** Restore: **/
listView.scrollTo(savedX, savedY);

2
回答に誤りがありました。このメソッドはsetSelectionと呼ばれます
Janusz

アイデアはうまく機能しますが、疑似問題があります。最初に表示される位置は少しだけ表示される場合があり(行のほんの一部に過ぎない場合があります)、setSelection()は、復元時にこの行を完全に表示するように設定します製。
rantravee

私の2番目のオプションを見てください。私はちょうどそれを私の最初の答えに追加しました
フランチェスコラウリタ

27
view.getScrollX()およびview.getScrollY()は常に0を返します。
rantravee 2010年

3
View.getChildAt()およびView.getTop()を使用して、上記の(受け入れられた)ソリューションを見てください。ListViewは内部でスクロールを維持するため、ListViewでView.getScrollY()を使用することはできません。
イアン

17

これについて何か面白いものを見つけました。

私はsetSelectionとscrolltoXYを試してみましたが、まったく機能しませんでした。リストは同じ位置に留まり、試行錯誤の結果、次のコードが機能しました。

final ListView list = (ListView) findViewById(R.id.list);
list.post(new Runnable() {            
    @Override
    public void run() {
        list.setSelection(0);
    }
});

Runnableをポストする代わりにrunOnUiThreadを試しても機能しない(少なくとも一部のデバイスでは)

これは、単純明快なはずの何かに対する非常に奇妙な回避策です。


1
同じ問題が発生しました!そしてsetSelectionFromTop()動作しません。
ofavre

+1。listnew.post()は、一部のデバイスでは機能せず、一部のデバイスでは機能しない場合がありますが、runOnUIThreadは正常に機能します。
Omar Rehman

@Omar、これが機能しないデバイスとOSの例をいくつか教えてください。HTC G2(2.3.4)とGalaxy Nexus(4.1.2)を試しましたが、どちらでも動作しました。このスレッドの他の回答は、どのデバイスでも機能しませんでした。
Dan J

2
listview.postは、4.0.4のGalaxy Noteでは正常に機能しますが、2.3.6のNexus Oneでは機能しません。ただし、onOnUIThread(action)は両方のデバイスで正常に動作します。
Omar Rehman 2013年

11

注意!!ListView.getFirstVisiblePosition()が0の場合、onSaveState()が正しく機能しないというAbsListViewのバグがあります。

したがって、画面の大部分を占める大きな画像があり、2番目の画像までスクロールしたが、最初の画像の一部が表示されている場合、スクロール位置は保存されません...

AbsListView.java:1650から(私のコメント)

// this will be false when the firstPosition IS 0
if (haveChildren && mFirstPosition > 0) {
    ...
} else {
    ss.viewTop = 0;
    ss.firstId = INVALID_POSITION;
    ss.position = 0;
}

ただし、この状況では、以下のコードの「トップ」が負の数になり、状態が正しく復元されない他の問題が発生します。したがって、「トップ」が負の場合、次の子を取得します

// save index and top position
int index = getFirstVisiblePosition();
View v = getChildAt(0);
int top = (v == null) ? 0 : v.getTop();

if (top < 0 && getChildAt(1) != null) {
    index++;
    v = getChildAt(1);
    top = v.getTop();
}
// parcel the index and top

// when restoring, unparcel index and top
listView.setSelectionFromTop(index, top);

それは魅力のように機能しますが、私はそれを完全に理解していません。最初のアイテムがまだ表示されている場合、次の子を取得することはどのように意味がありますか?新しいインデックスを使用してsetSelectionFromTopを実行すると、2番目の子からリストが表示されますか?どのようにして最初のものをまだ見ていますか?
tafi

@tafi、最初のアイテムは「部分的に」表示される可能性があります。したがって、そのアイテムの上部は画面の上にあり、したがって負の数になります。(これにより、思い出せない他の問題が発生します...)したがって、2番目の項目の「上部」を配置に使用します。これは、常に(?)利用可能である必要があります。そうしないと、最初にスクロールが発生しません。 !
aaronvargas

6
private Parcelable state;
@Override
public void onPause() {
    state = mAlbumListView.onSaveInstanceState();
    super.onPause();
}

@Override
public void onResume() {
    super.onResume();

    if (getAdapter() != null) {
        mAlbumListView.setAdapter(getAdapter());
        if (state != null){
            mAlbumListView.requestFocus();
            mAlbumListView.onRestoreInstanceState(state);
        }
    }
}

もういい


こんにちは、上のコードは、インスタンス状態がアクティビティ間で保存されていないRecyclerViewリストで私を助けますか?ここに次の質問を投稿しました:stackoverflow.com/questions/35413495/…
AJW 2016

6

この問題の解決策を探している人にとって、問題の根本は、リストビューアダプターを設定しているところにある可能性があります。アダプターをリストビューに設定すると、スクロール位置がリセットされます。考慮すべきことだけです。リストビューへの参照を取得した後、アダプターをonCreateViewに設定し、問題を解決しました。=)


1

誰もこれに言及しなかったので驚いたので、これを投稿しています。

ユーザーが[戻る]ボタンをクリックした後、リストビューから出たときと同じ状態でリストビューに戻ります。

このコードは「上」ボタンをオーバーライドして「戻る」ボタンと同じように動作するため、リストビュー->詳細->リストビューに戻る(他のオプションなし)の場合、これはスクロール位置とコンテンツを維持する最も簡単なコードです。リストビューで。

 public boolean onOptionsItemSelected(MenuItem item) {
     switch (item.getItemId()) {
         case android.R.id.home:
             onBackPressed();
             return(true);
     }
     return(super.onOptionsItemSelected(item)); }

注意:詳細アクティビティから別のアクティビティに移動できる場合、[上へ]ボタンをクリックするとそのアクティビティに戻るので、これを機能させるには[戻る]ボタンの履歴を操作する必要があります。



1

最善の解決策は:

// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());

// ...

// restore index and position
mList.post(new Runnable() {
    @Override
    public void run() {
      mList.setSelectionFromTop(index, top);
   }
});

あなたはポストとスレッドで電話しなければなりません!


1

リロードする前に状態を保存し、後で復元すると、リロード後のスクロール状態を維持できます。私の場合、非同期ネットワークリクエストを作成し、完了後にコールバックでリストをリロードしました。これが状態を復元する場所です。コードサンプルはKotlinです。

val state = myList.layoutManager.onSaveInstanceState()

getNewThings() { newThings: List<Thing> ->

    myList.adapter.things = newThings
    myList.layoutManager.onRestoreInstanceState(state)
}

0

アクティビティでホストされているフラグメントを使用している場合は、次のようなことができます。

public abstract class BaseFragment extends Fragment {
     private boolean mSaveView = false;
     private SoftReference<View> mViewReference;

     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          if (mSaveView) {
               if (mViewReference != null) {
                    final View savedView = mViewReference.get();
                    if (savedView != null) {
                         if (savedView.getParent() != null) {
                              ((ViewGroup) savedView.getParent()).removeView(savedView);
                              return savedView;
                         }
                    }
               }
          }

          final View view = inflater.inflate(getFragmentResource(), container, false);
          mViewReference = new SoftReference<View>(view);
          return view;
     }

     protected void setSaveView(boolean value) {
           mSaveView = value;
     }
}

public class MyFragment extends BaseFragment {
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          setSaveView(true);
          final View view = super.onCreateView(inflater, container, savedInstanceState);
          ListView placesList = (ListView) view.findViewById(R.id.places_list);
          if (placesList.getAdapter() == null) {
               placesList.setAdapter(createAdapter());
          }
     }
}

0

ListView自分のスクロール位置を保存または復元する場合、Androidフレームワークにすでに実装されている機能を本質的に複製しています。ListView@aaronvargasはバグがあるに述べたように:1つの注意点を除いてちょうどよく自分自身でリストア細かいスクロール位置AbsListViewそれは、最初のリスト項目の細かいスクロール位置を復元することはできません。それにもかかわらず、スクロール位置を復元する最良の方法は、それを復元しないことです。Androidフレームワークはそれをよりよくします。次の条件を満たしていることを確認してください。

  • setSaveEnabled(false)メソッドを呼び出さずandroid:saveEnabled="false"、xmlレイアウトファイルのリストに属性を設定していないことを確認してください
  • 以下のためのExpandableListViewオーバーライドlong getCombinedChildId(long groupId, long childId)が正の長い数(クラスのデフォルト実装返すようにメソッドBaseExpandableListAdapter戻り負の数)。次に例を示します。

@Override
public long getChildId(int groupPosition, int childPosition) {
    return 0L | groupPosition << 12 | childPosition;
}

@Override
public long getCombinedChildId(long groupId, long childId) {
    return groupId << 32 | childId << 1 | 1;
}

@Override
public long getGroupId(int groupPosition) {
    return groupPosition;
}

@Override
public long getCombinedGroupId(long groupId) {
    return (groupId & 0x7FFFFFFF) << 32;
}
  • ListViewまたはExpandableListViewがフラグメントで使用されている場合は、アクティビティの再作成時にフラグメントを再作成しないでください(画面の回転後など)。findFragmentByTag(String tag)メソッドでフラグメントを取得します。
  • ListViewがありandroid:id、それが一意であることを確認してください。

最初のリストアイテムに関する前述の警告を回避するにはListView、位置0の特別なダミーゼロピクセル高さビューを返すようにアダプターを作成します。以下は、スクロール位置が明示的に保存されていないのに、プロジェクトの細かいスクロール位置を表示ListViewしてExpandableListView復元する簡単なサンプルプロジェクトです。/復元。細かいスクロール位置は、一時的に他のアプリケーションに切り替えたり、画面を2度回転させたり、テストアプリケーションに切り替えたりする複雑なシナリオでも完全に復元されます。アプリケーションを明示的に終了する([戻る]ボタンを押す)場合、スクロール位置は保存されません(他のすべてのビューも状態を保存しません)。 https://github.com/voromto/RestoreScrollPosition/releases


0

SimpleCursorAdapterを使用してLoaderManager.LoaderCallbacksを実装するListActivityから派生したアクティビティの場合、onReset()で位置を復元することはできませんでした。アクティビティがほとんど常に再起動され、詳細ビューが閉じられたときにアダプタが再ロードされたためです。トリックは、onLoadFinished()で位置を復元することでした。

onListItemClick():

// save the selected item position when an item was clicked
// to open the details
index = getListView().getFirstVisiblePosition();
View v = getListView().getChildAt(0);
top = (v == null) ? 0 : (v.getTop() - getListView().getPaddingTop());

onLoadFinished():

// restore the selected item which was saved on item click
// when details are closed and list is shown again
getListView().setSelectionFromTop(index, top);

onBackPressed():

// Show the top item at next start of the app
index = 0;
top = 0;

0

ここで提供されているソリューションはどちらも私にはうまくいかないようです。私の場合、私はで置き換えているListViewin を持っているので、フラグメントが表示されるたびに新しいインスタンスが作成されます。これは、状態をのメンバーとして保存できないことを意味します。FragmentFragmentTransactionFragmentListViewFragment

代わりに、状態をカスタムApplicationクラスに格納することになりました。以下のコードは、これがどのように機能するのかをあなたに与えるでしょう:

public class MyApplication extends Application {
    public static HashMap<String, Parcelable> parcelableCache = new HashMap<>();


    /* ... code omitted for brevity ... */
}

 

public class MyFragment extends Fragment{
    private ListView mListView = null;
    private MyAdapter mAdapter = null;


    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mAdapter = new MyAdapter(getActivity(), null, 0);
        mListView = ((ListView) view.findViewById(R.id.myListView));

        Parcelable listViewState = MyApplication.parcelableCache.get("my_listview_state");
        if( listViewState != null )
            mListView.onRestoreInstanceState(listViewState);
    }


    @Override
    public void onPause() {
        MyApplication.parcelableCache.put("my_listview_state", mListView.onSaveInstanceState());
        super.onPause();
    }

    /* ... code omitted for brevity ... */

}

基本的な考え方は、フラグメントインスタンスの外側に状態を格納することです。アプリケーションクラスに静的フィールドを作成するという考えが気に入らない場合は、フラグメントインターフェースを実装し、アクティビティに状態を保存することで実現できると思います。

別の解決策はに保存するSharedPreferencesことですが、少し複雑になるため、アプリの起動間で状態を維持したくない場合を除き、アプリケーションの起動時にそれをクリアする必要があります。

 

また、「最初のアイテムが表示されているときにスクロール位置が保存されない」ことを回避するために、0px高さのあるダミーの最初のアイテムを表示できます。これはgetView()、次のようにアダプターをオーバーライドすることで実現できます。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if( position == 0 ) {
        View zeroHeightView = new View(parent.getContext());
        zeroHeightView.setLayoutParams(new ViewGroup.LayoutParams(0, 0));
        return zeroHeightView;
    }
    else
        return super.getView(position, convertView, parent);
}

0

私の答えはFirebaseで、ポジション0は回避策です

Parcelable state;

DatabaseReference everybody = db.getReference("Everybody Room List");
    everybody.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            state = listView.onSaveInstanceState(); // Save
            progressBar.setVisibility(View.GONE);
            arrayList.clear();
            for (DataSnapshot messageSnapshot : dataSnapshot.getChildren()) {
                Messages messagesSpacecraft = messageSnapshot.getValue(Messages.class);
                arrayList.add(messagesSpacecraft);
            }
            listView.setAdapter(convertView);
            listView.onRestoreInstanceState(state); // Restore
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
        }
    });

そしてconvertView

位置0 a使用していない空白のアイテムを追加する

public class Chat_ConvertView_List_Room extends BaseAdapter {

private ArrayList<Messages> spacecrafts;
private Context context;

@SuppressLint("CommitPrefEdits")
Chat_ConvertView_List_Room(Context context, ArrayList<Messages> spacecrafts) {
    this.context = context;
    this.spacecrafts = spacecrafts;
}

@Override
public int getCount() {
    return spacecrafts.size();
}

@Override
public Object getItem(int position) {
    return spacecrafts.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@SuppressLint({"SetTextI18n", "SimpleDateFormat"})
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.message_model_list_room, parent, false);
    }

    final Messages s = (Messages) this.getItem(position);

    if (position == 0) {
        convertView.getLayoutParams().height = 1; // 0 does not work
    } else {
        convertView.getLayoutParams().height = RelativeLayout.LayoutParams.WRAP_CONTENT;
    }

    return convertView;
}
}

ユーザーの邪魔をせずにこの作品を一時的に見たことがあります。


0

以下のコードを使用してください:

int index,top;

@Override
protected void onPause() {
    super.onPause();
    index = mList.getFirstVisiblePosition();

    View v = challengeList.getChildAt(0);
    top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());
}

そして、あなたのデータを更新するときはいつでも、以下のコードを使用してください:

adapter.notifyDataSetChanged();
mList.setSelectionFromTop(index, top);

0

私はFirebaseListAdapterを使用していますが、ソリューションを機能させることができませんでした。私はこれをやった。よりエレガントな方法があると思いますが、これは完全で実用的なソリューションです。

onCreateの前:

private int reset;
private int top;
private int index;

FirebaseListAdapterの内部:

@Override
public void onDataChanged() {
     super.onDataChanged();

     // Only do this on first change, when starting
     // activity or coming back to it.
     if(reset == 0) {
          mListView.setSelectionFromTop(index, top);
          reset++;
     }

 }

onStart:

@Override
protected void onStart() {
    super.onStart();
    if(adapter != null) {
        adapter.startListening();
        index = 0;
        top = 0;
        // Get position from SharedPrefs
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
        top = sharedPref.getInt("TOP_POSITION", 0);
        index = sharedPref.getInt("INDEX_POSITION", 0);
        // Set reset to 0 to allow change to last position
        reset = 0;
    }
}

onStop:

@Override
protected void onStop() {
    super.onStop();
    if(adapter != null) {
        adapter.stopListening();
        // Set position
        index = mListView.getFirstVisiblePosition();
        View v = mListView.getChildAt(0);
        top = (v == null) ? 0 : (v.getTop() - mListView.getPaddingTop());
        // Save position to SharedPrefs
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
        sharedPref.edit().putInt("TOP_POSITION" + "", top).apply();
        sharedPref.edit().putInt("INDEX_POSITION" + "", index).apply();
    }
}

FirebaseRecyclerAdapterについてもこれを解決する必要があったので、そのためのソリューションもここに投稿します。

onCreateの前:

private int reset;
private int top;
private int index;

FirebaseRecyclerAdapterの内部:

@Override
public void onDataChanged() {
    // Only do this on first change, when starting
    // activity or coming back to it.
    if(reset == 0) {
        linearLayoutManager.scrollToPositionWithOffset(index, top);
        reset++;
    }
}

onStart:

@Override
protected void onStart() {
    super.onStart();
    if(adapter != null) {
        adapter.startListening();
        index = 0;
        top = 0;
        // Get position from SharedPrefs
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
        top = sharedPref.getInt("TOP_POSITION", 0);
        index = sharedPref.getInt("INDEX_POSITION", 0);
        // Set reset to 0 to allow change to last position
        reset = 0;
    }
}

onStop:

@Override
protected void onStop() {
    super.onStop();
    if(adapter != null) {
        adapter.stopListening();
        // Set position
        index = linearLayoutManager.findFirstVisibleItemPosition();
        View v = linearLayoutManager.getChildAt(0);
        top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop());
        // Save position to SharedPrefs
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
        sharedPref.edit().putInt("TOP_POSITION" + "", top).apply();
        sharedPref.edit().putInt("INDEX_POSITION" + "", index).apply();
    }
}

0

Ryan Newsomの優れた答えを明確にし、フラグメントに合わせて調整します。通常のケースでは、「マスター」ListViewフラグメントから「詳細」フラグメントに移動してから、「マスター」に戻ります。

    private View root;
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
           if(root == null){
             root = inflater.inflate(R.layout.myfragmentid,container,false);
             InitializeView(); 
           } 
           return root; 
        }

    public void InitializeView()
    {
        ListView listView = (ListView)root.findViewById(R.id.listviewid);
        BaseAdapter adapter = CreateAdapter();//Create your adapter here
        listView.setAdpater(adapter);
        //other initialization code
    }

ここでの「魔法」は、詳細フラグメントからListViewフラグメントに戻るときに、ビューが再作成されず、ListViewのアダプターを設定しないため、すべてが残ったままになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.