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
.
답변
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);
}
}
답변
@ (Kirk Woll)에서 제안한 솔루션을 채택했으며 나에게 효과적입니다. “Contacts”앱의 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 장치에서는 전화 방향을 변경하거나 항목을 편집하고 목록으로 돌아갈 때 모두 작동합니다.
답변
매우 간단한 방법 :
/** 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);
답변
나는 이것에 대해 흥미로운 것을 발견했다.
나는 setSelection과 scrolltoXY를 시도했지만 전혀 작동하지 않았다. 일부 시행 착오 후에 목록이 같은 위치에 남아 있었다. 다음 코드가 작동한다.
final ListView list = (ListView) findViewById(R.id.list);
list.post(new Runnable() {
@Override
public void run() {
list.setSelection(0);
}
});
Runnable을 게시하는 대신 runOnUiThread를 시도해도 작동하지 않습니다 (적어도 일부 장치에서는)
이것은 똑바로 나아가 야 할 무언가에 대한 매우 이상한 해결 방법입니다.
답변
주의!! AbsListView에는 ListView.getFirstVisiblePosition ()이 0 인 경우 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);
답변
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);
}
}
}
충분 해