我有很長的ListView
,用戶可以在返回到前一個屏幕前滾動。當用戶再次打開此ListView
時,我希望列表滾動到與之前相同的點。任何想法如何實現這一目標?返回ListView時維護/保存/恢復滾動位置
回答
試試這個:
// 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
的頂部開始定位其頂邊的偏移量一起調用。
不太瞭解這是如何工作的。我只使用listView.getFirstVisiblePosition(),並理解,但不知道這裏發生了什麼。任何簡單解釋的機會? :) – HXCaine 2010-09-01 22:25:43
因此ListView.getFirstVisiblePosition()返回頂部可見列表項。但是這個項目可能會部分滾動到視圖外,如果你想恢復列表的確切滾動位置,你需要獲得這個偏移量。因此,ListView.getChildAt(0)返回頂部列表項的View,然後View.getTop()從ListView的頂部返回其相對偏移量。然後,爲了恢復ListView的滾動位置,我們調用了ListView.setSelectionFromTop()和我們需要的項目的索引,以及一個偏移量,以便從ListView的頂部定位它的上邊緣。全清? – ian 2010-09-02 07:17:22
這可以更簡單地使用一行來保存:'int index = mList.getFirstVisiblePosition();'並且只有一行可以恢復:'mList.setSelectionFromTop(index,0);'。雖然(+1)很好的答案!我一直在尋找一個優雅的解決方案來解決這個問題。 – Phil 2012-01-03 18:01:47
一個非常簡單的方法:
/** 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);
Parcelable state;
@Override
public void onPause() {
// Save ListView state @ onPause
Log.d(TAG, "saving listview state @ onPause");
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);
}
}
我採用了@(柯克沃爾)建議的解決方案,它適用於我。我也在「聯繫人」應用的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」是我的函數來檢索數據從數據庫並將其放到列表中。
在我的Froyo設備上,當您更改手機方向以及編輯項目並返回列表時,此功能都可以使用。
偉大的代碼工作非常好,我的列表視圖謝謝你這麼much..really欣賞它 – user1106888 2013-02-06 22:57:18
謝謝somuch它工作得很好..... – praveenb 2013-02-07 10:53:22
該解決方案爲我工作。其他人沒有。如何保存/恢復ListView實例狀態的行爲與在ListView中刪除和插入項目有關? – Bryan 2013-02-19 22:12:20
我發現了一些有趣的東西。
我試圖爲setSelection和scrolltoXY但它並沒有在所有的工作,該列表保持在相同的位置,我得到了工作,經過一番試驗和錯誤下面的代碼,不會
final ListView list = (ListView) findViewById(R.id.list);
list.post(new Runnable() {
@Override
public void run() {
list.setSelection(0);
}
});
如果相反的張貼可運行的你嘗試runOnUiThread它也不起作用(至少在某些設備上)
這是一個非常奇怪的解決方法,應該是直截了當的東西。
我遇到過同樣的問題! 'setSelectionFromTop()'不起作用。 – ofavre 2012-02-03 23:29:14
+1。 listnew.post()不適用於某些設備,在某些其他設備上,它在某些情況下不起作用,但runOnUIThread正常工作。 – 2012-11-22 09:21:20
@Omar,你能舉出一些設備和操作系統的例子嗎?我嘗試了一款HTC G2(2.3.4)和一款Galaxy Nexus(4.1.2),並且它們都可以使用。此線程中沒有任何其他答案適用於我的任何設備。 – 2013-01-19 18:39:09
注意!如果ListView.getFirstVisiblePosition()爲0,則AbsListView中存在一個錯誤,它不允許onSaveState()正常工作。
所以,如果你有一個佔據了屏幕的大部分大型圖片和滾動到第二圖像,但一點點的第一次的顯示時,滾動位置將不會被保存...
從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);
張貼這是因爲我很驚訝沒有人提到過這一點。
用戶單擊後退按鈕後,他將返回到列表視圖,其狀態與退出時的狀態相同。
這段代碼將覆蓋「向上」按鈕的行爲方式與後退按鈕的行爲相同,因此在Listview - > Details - >返回列表視圖(並且沒有其他選項)的情況下,這是維護scrollposition和listview中的內容。
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return(true);
}
return(super.onOptionsItemSelected(item)); }
注意:如果你可以去到另一個活動從細節活性向上按鈕即可返回回到了那個活動,所以你將不得不操縱後退按鈕歷史在爲了這個工作。
是不是簡單的android:saveEnabled="true"
在ListView xml聲明中就夠了?
android:saveEnabled默認設置爲true。這沒有做任何事情。 – Brad 2014-06-05 01:35:51
沒有。這還不夠,你必須遵循http://stackoverflow.com/questions/3014089/maintain-save-restore-scroll-position-when-returning-to-a-listview?answertab=active#tab-top或http: //stackoverflow.com/questions/3014089/maintain-save-restore-scroll-position-when-returning-to-a-listview?answertab=active#answer-5688490 – 2014-10-02 23:07:26
如果您使用託管在一個活動的片段,你可以做這樣的事情:
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());
}
}
}
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);
}
}
}
這足以
如果要保存/自己恢復的ListView
滾動位置你基本上覆制了已經在android框架中實現的功能。 ListView
恢復精細的滾動位置,除了一個警告:就像@aaronvargas提到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
它是唯一的。
爲了避免與第一個列表項前面提到的警告,你可以手藝適配器的方式,在0位置 這裏返回專用虛擬0像素高度視圖爲ListView
是簡單的示例項目顯示ListView
和ExpandableListView
恢復自己的精滾動位置,而他們的滾動位置不明確保存/恢復。即使對於臨時切換到某些其他應用程序,雙屏旋轉和切換回測試應用程序的複雜場景,精細滾動位置也可以完美恢復。請注意,如果您正在顯式退出應用程序(通過按「後退」按鈕),則不會保存滾動位置(以及所有其他視圖不會保存其狀態)。 https://github.com/voromto/RestoreScrollPosition/releases
最好的辦法是:
// 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);
}
});
你必須撥打郵政與螺紋!
對於從使用SimpleCursorAdapter它沒有工作,以恢復onReset()的位置實現LoaderManager.LoaderCallbacks ListActivity派生的活動,因爲活動幾乎總是重新和適配器被加載時的細節視圖被關閉。訣竅是恢復在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;
對於一些尋找解決此問題的方法,問題的根源可能是您設置列表視圖適配器的位置。在列表視圖上設置適配器後,它將重置滾動位置。只是需要考慮。在我們獲取對listview的引用之後,我將適配器設置到了我的onCreateView中,併爲我解決了這個問題。 =)
如果在重新加載之前保存狀態並在之後進行恢復,則可以在重新加載後保持滾動狀態。在我的情況下,我做了一個異步網絡請求,並在完成後在回調中重新加載列表。這是我恢復狀態的地方。代碼示例是Kotlin。
val state = myList.layoutManager.onSaveInstanceState()
getNewThings() { newThings: List<Thing> ->
myList.adapter.things = newThings
myList.layoutManager.onRestoreInstanceState(state)
}
- 1. 維護JTextArea滾動位置
- 2. SharePoint維護滾動位置
- 3. 如何保存ListView的滾動位置
- 4. 如何保存並恢復Swift中的NSScrollView滾動位置?
- 5. jScroll在返回頁面時保存滾動位置
- 6. 如何在滾動後保存和維護ListView項目狀態?
- 7. Jquerymobile Scrollview在滾動後返回到原始位置。不保存滾動位置
- 8. 維護大HTML頁面的滾動位置時,客戶端返回
- 9. 在列表中維護滾動位置
- 10. 在WebView中維護滾動位置
- 11. Silverlight維護列表框滾動位置
- 12. 列表不維護滾動位置
- 13. 在JavaScript中維護滾動位置window.open()
- 14. ListView如何在destroyView後恢復滾動位置?
- 15. 如何在Android中保存和恢復ListView位置
- 16. 恢復以前的滾動位置
- 17. 維護滾動位置和回發中的選定控件
- 18. 超鏈接回發後維護滾動位置
- 19. 在回發頁面中維護頁面內的滾動位置
- 20. 保存滾動位置
- 21. 如何返回上一頁並在動畫之後恢復滾動位置?
- 22. contenteditable:保存和恢復插入位置
- 23. jQuery UI保存/恢復丟棄位置
- 24. 保存和恢復NSTextView的位置
- 25. 如何在移除滾動條時維護html內容位置?
- 26. 在添加行時維護TextBox滾動位置
- 27. 在恢復時維護URL結構
- 28. 通過瀏覽器「返回」或鏈接返回時,保留滾動位置?
- 29. 在定位更改上維護WebView內容滾動位置
- 30. ListView中的片段不能保存滾動位置
我認爲尤金Mymrin /喬治Barchiesi提到的解決方案比接受的答案 – 2012-07-02 10:54:27
由「喬治Barchiesi」工作對我給出的解決方案更好。其他解決方案不適合我。 – Bryan 2013-02-19 22:14:55