2013-02-05 12 views
20

我在修改適配器數據時保留列表視圖的滾動位置時遇到了一些麻煩。有沒有辦法來防止列表視圖滾動到其頂部的位置,當其適配器的數據更改?

什麼我目前做的是創造一個ListFragment的onCreate定製ArrayAdapter(與重寫getView方法),然後將其分配給它的列表:

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

然後,當我收到從定期獲取一切裝載機新的數據,我這樣做是在其onLoadFinished回調:

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

的問題是,調用clear()重置ListView的滾動位置。刪除該呼叫會保留該位置,但顯然會將舊項目留在列表中。

這樣做的正確方法是什麼?

+1

你可以得到的位置之前,然後設置位置回來。 –

回答

34

正如您自己指出的那樣,調用'clear()'會導致位置重置爲頂部。

擺弄滾動位置等是一個黑客得到這個工作。

如果從ArrayAdapter你CustomListAdapter子類,這可能是問題:

調用清除(),稱之爲 'notifyDataSetChanged()'。您可以防止這種情況:

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(); 

我沒有嘗試這樣做自己,但試試吧:)

+0

我在創建列表適配器時關閉了informonchange(對不起,在我的原始文章中沒有提及它)。當我手動通知時,我不知道它會被打開。我將需要測試這個。 – urandom

+1

這就是答案。謝謝,比「更新後的滾動更好」的黑客更好:)太糟糕了(這個奇怪的,恕我直言)的行爲沒有記錄。 – urandom

+0

在哪裏我必須使用此代碼?請讓我知道這 – Prasad

6

退房:Maintain/Save/Restore scroll position when returning to a ListView

使用此保存位置在ListView調用.clear(前),.addAll(),和。 notifyDataSetChanged()。

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

更新的ListView適配器後,ListView的項目將被改變,然後將新位置:

mList.setSelectionFromTop(index, top); 

基本上你可以節省你的位置和向後滾動到它,保存的ListView狀態或整個應用程序狀態。

其他有用的鏈接:

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

保存狀態: Android ListView y position

問候,

請讓我知道,如果這有助於!

+0

這種作品,但感覺有點不好意思。主要是因爲,即使列表視圖本身不移動,每當更新發生時滾動條都會閃爍。每秒鐘更新一次,看起來就像一盞巨大的灰色閃爍燈。我可以隱藏滾動條本身,但它非常有用。 – urandom

+0

這個問題已經在這裏回答了很多次。我只是舉一個例子:) –

+0

爲了修復我的滾動條眨眼:'mList.setVerticalScrollBarEnabled(false)'在開頭,'mList.setVerticalScrollBarEnabled(true)'在結尾處,我將它添加到您的答案中。雖然我真的希望有點少hackish :) – urandom

-1

在您的擴展/表適配器,把這種方法

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

從你的活動,要更新列表,把這段代碼

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

擴展列表的情況下查看,您將使用 mDataListView.getExpandableListAdapter的()代替 mDataListView.getAdapter()

相關問題