2013-02-05 16 views
20

アダプタのデータを変更するときに、リストビューのスクロール位置を保持するのに少し問題があります。アダプタのデータが変更されたときにリストビューがスクロールしてトップ位置に表示されないようにする方法はありますか?

私が現在やっていることはListFragmentのonCreateでカスタム(上書きGetViewメソッドを持つ)ArrayAdapterを作成し、そのリストに割り当てることです:

mListAdapter = new CustomListAdapter(getActivity()); 
mListAdapter.setNotifyOnChange(false); 
setListAdapter(mListAdapter); 

その後、私は受け取ります定期的にすべてのものを取り出し、ローダからの新しいデータが、私はそのonLoadFinishedコールバックで次の操作を行います。

mListAdapter.clear(); 
mListAdapter.addAll(data.items); 
mListAdapter.notifyDataSetChanged(); 

問題がclear()リセットリストビューのスクロール位置を呼び出す、です。その呼び出しを削除すると位置は保持されますが、明らかに古い項目はリストに残ります。

これを行う適切な方法は何ですか?

+1

あなたは前の位置を取得し、バックの位置を設定することができます。 –

答えて

34

あなたが指摘したように、 'clear()'を呼び出すと、その位置が先頭にリセットされます。

スクロール位置などの操作は、この作業を行うためのハックです。

ArrayAdapterからごCustomListAdapterサブクラスは、これが問題である可能性があります:

コールがクリアする()、 ')(notifyDataSetChanged' を呼び出します。 は

public void refresh(List<MyDataClass> dataList) { 
    mDataList.clear(); 
    mDataList.addAll(events); 
    notifyDataSetChanged(); 
} 

そして、あなたの活動からこのメソッドを置く

、私はこれを自分で試してみましたが、それを試してみてください:)

+0

私はリストアダプターを作成したときにnotifyonchangeをオフにしました(私の元の投稿には言及していないのは申し訳ありません)。私は手動で通知するときにそれが再びオンになることを知らなかった。私はこれをテストする必要があります。 – urandom

+1

それは答えです。ありがとう、 "スクロールアップ後の更新"ハッキングよりもはるかに良い:)あまりにも悪い(この奇妙な、imho)の動作は文書化されていません。 – urandom

+0

私はこのコードをどこで使う必要がありますか?私にこれを知らせてください – Prasad

6

チェックアウト:Maintain/Save/Restore scroll position when returning to a ListView

使用このお.clear(呼び出す前に、リストビューで位置を保存するために)、.addAll()、および。 notifyDataSetChanged()。

int index = mList.getFirstVisiblePosition(); 
View v = mList.getChildAt(0); 
int top = (v == null) ? 0 : v.getTop(); 

ListViewコントロールアダプタを更新した後、リストビューの項目が変更され、その後、新しい位置に設定されます。

mList.setSelectionFromTop(index, top); 

基本的にあなたがあなたの位置を保存し、それに戻ってスクロールし、リストビューステートを保存したりすることができますがアプリケーション全体の状態。

その他の便利なリンク:

保存位置: How to save and restore ListView position in Android

保存状態: Android ListView y position

よろしく、

このことができます場合は私に知らせてください!

+0

この種の作品は、ちょっとハッキリしています。ほとんどの場合、リストビュー自体は移動しませんが、更新が行われるたびにスクロールバーが点滅するためです。 1秒おきに更新すると、巨大な灰色の点滅のように見えます。私はスクロールバー自体を隠すことができますが、それは非常に便利です。 – urandom

+0

この質問はここで何度も答えられています。私は単純に一つの例を挙げています:) –

+0

私はスクロールバーの点滅を修正するためにこれをあなたの答えに追加します。最後に 'mList.setVerticalScrollBarEnabled(false)'と最後に 'mList.setVerticalScrollBarEnabled(true)'を追加します。私は本当に何か少しハックしたいと思っています:) – urandom

-1

あなたの拡張/一覧アダプタではなかった

mListAdapter.setNotifyOnChange(false); // Prevents 'clear()' from clearing/resetting the listview 
mListAdapter.clear(); 
mListAdapter.addAll(data.items); 
// note that a call to notifyDataSetChanged() implicitly sets the setNotifyOnChange back to 'true'! 
// That's why the call 'setNotifyOnChange(false) should be called first every time (see call before 'clear()'). 
mListAdapter.notifyDataSetChanged(); 

:あなたはこれを防ぐことができます、あなたがリストを更新したい場合は、このコードを配置

if (mDataListView.getAdapter() == null) { 
    MyDataAdapter myDataAdapter = new MyDataAdapter(mContext, dataList); 
    mDataListView.setAdapter(myDataAdapter); 
} else { 
    ((MyDataAdapter)mDataListView.getAdapter()).refresh(dataList); 
} 

拡張可能なリストビューの場合は、あなたの代わりに mDataListView.getAdapter(の mDataListView.getExpandableListAdapter()を使用します)

関連する問題