更新
基本上,bbrakenhoff回答了我的问题,但还有一件事需要解决。如何更新EndlessFeedAdapter(mEndlsFidAdptr)的内容?我需要清除该项目然后重新加载。我正在使用CWAC EndlessAdapater。是否有清除内容的技巧或者编写方法更容易?完成此操作后,滚动位置应该是维护。
我从服务器获取数据并在内容更改时更新EndlessFeedAdapter。每次我更新我的适配器并重新加载内容。问题是重新加载后我的列表会跳回到顶部,因为我的滚动位置没有被保持。我已经广泛尝试了setSelection和setSelectionFromTop,但没有得到积极的结果。
如何在更新适配器后保持滚动位置?
我一直在寻找答案的论坛,但似乎没有任何工作。
我尝试了所有这些:Maintain/Save/Restore scroll position when returning to a ListView
这不起作用:
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
// restore index and position
mList.setSelectionFromTop(index, top);
也不是这样:
// Save ListView state
Parcelable state = listView.onSaveInstanceState();
// Set new items
listView.setAdapter(adapter);
// Restore previous state (including selected item index and scroll position)
listView.onRestoreInstanceState(state);
也不是其他解决方案,例如设置runnable或设置scrollPositionY。设置notifyDataChanged不起作用,因为我从不同的列表加载。
我的代码:
private void showFeed() {
if (mFeedActivity.mInFeed) {
mQuickReturnView.setVisibility(View.VISIBLE);
} else {
mQuickReturnView.setVisibility(View.GONE);
}
Activity actvt= getActivity();
if (actvt == null || mFeedListView == null) return;
actvt.invalidateOptionsMenu();
mFeedListView.setVisibility(View.VISIBLE);
//updated with help from response
if (mAdapter == null){
mAdapter = new FeedAdapter(actvt, 0, mFeed.getItems().getFeedItemList(), this);
} else {
mAdapter.clear();
mAdapter.addAll(mFeed.getItems().getFeedItemList());
mAdapter.notifyDataSetChanged();
}
mEndlsFidAdptr = new EndlessFeedAdapter(actvt, mAdapter, R.layout.progress_row, mFeed.isShowMoreBar(),
mEndlsFidAdptr.setRunInBackground(false);
//Parcelable state = mFeedListView.onSaveInstanceState();
mFeedListView.setAdapter(mEndlsFidAdptr);
//mFeedListView.onRestoreInstanceState(state);
mFeedListView.setSelectionFromTop(mFirstVisibleItem, mVisibleItemOffset);
if(!(mFeedScope.equalsIgnoreCase(FeedScope.BOOKMARKS.xmlValue()) ||
mFeedScope.equalsIgnoreCase(FeedScope.DOCUMENT.xmlValue()) ||
mFeedScope.equalsIgnoreCase(FeedScope.NOTIFICATIONS.xmlValue()) ||
mFeedScope.equalsIgnoreCase(FeedScope.RECEIVED_TASKS.xmlValue()) ||
mFeedScope.equalsIgnoreCase(FeedScope.SEND_TASKS.xmlValue()))) {
mFeedListView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
mFeedListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mCanShowHide = scrollState == SCROLL_STATE_FLING;
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
View v = mFeedListView.getChildAt(0);
//View v = null;
if(!mFeedActivity.mInFeed || v == null)
return;
int top = v.getTop();
if(mIsAnimating) {
mVisibleItemOffset = top;
mFirstVisibleItem = firstVisibleItem;
return;
}
boolean hide = false;
boolean show = false;
float stickyHeight = getResources().getDimension(R.dimen.sticky_height);
if(firstVisibleItem == mFirstVisibleItem) {
if((top + stickyHeight) < mVisibleItemOffset) {
// Content scrolled down
// if shown then hide quickactionview
if(mQuickReturnShown) {
hide = true;
}
} else if (top > mVisibleItemOffset) {
// Content scrolled up
// if hidden then show quickactionview
if(!mQuickReturnShown) {
show = true;
}
}
} else if(firstVisibleItem > mFirstVisibleItem) {
// Content scrolled down
// if shown then hide quickactionview
if(mQuickReturnShown) {
hide = true;
}
} else if (firstVisibleItem < mFirstVisibleItem) {
// Content scrolled up
// if hidden then show quickactionview
if(!mQuickReturnShown) {
show = true;
}
}
if((show && mCanShowHide) || (top == 0 && !mQuickReturnShown)) {
mTranslateAnimation = new TranslateAnimation(0, 0, -mQuickReturnHeight, 0);
mTranslateAnimation.setDuration(DURATION_MILLIS);
mTranslateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
mIsAnimating = true;
}
@Override
public void onAnimationEnd(Animation animation) {
mIsAnimating = false;
mQuickReturnShown = true;
mQuickReturnView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
mQuickReturnView.startAnimation(mTranslateAnimation);
}
if(hide) {
mTranslateAnimation = new TranslateAnimation(0, 0, 0, -mQuickReturnHeight);
mTranslateAnimation.setDuration(DURATION_MILLIS);
mTranslateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
mIsAnimating = true;
}
@Override
public void onAnimationEnd(Animation animation) {
mIsAnimating = false;
mQuickReturnShown = false;
mQuickReturnView.setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(Animation animation) { }
});
mQuickReturnView.startAnimation(mTranslateAnimation);
}
mVisibleItemOffset = top;
mFirstVisibleItem = firstVisibleItem;
}
});
} else {
mFeedListView.setOnScrollListener(null);
}
mFeedListView.setSelectionFromTop(mFirstVisibleItem, mVisibleItemOffset);
//mFeedListView.scrollTo(mCurrentX,mCurrentY);
if(mFeed.getItems().getFeedItemList().size() == 0) {
mEmptyFeedView.setVisibility(View.VISIBLE);
}
}
感谢任何帮助!
答案 0 :(得分:2)
每次收到新数据时,您是否正在调用方法showFeed()?如果是,那么也许您可以尝试重新填充适配器,而不是每次都分配一个新适配器。
我不确切地知道你在适配器中做了什么,所以我会告诉你我是如何在我的一个应用程序中做到的。
在我的Activity / Fragment中,当我想用新项目更新列表时,我这样做:
private void refreshCalendar(ArrayList<CalendarDay> newCalendar) {
if (mAdapter == null) {
mAdapter = new CalendarAdapter(getActivity(), newCalendar);
mExpandableListView.setAdapter(mAdapter);
}
else {
mAdapter.refill(newCalendar);
}
restoreInstanceState();
}
在适配器中:
public void refill(ArrayList<CalendarDay> newCalendar) {
mCalendar.clear();
mCalendar.addAll(newCalendar);
notifyDataSetChanged();
}
答案 1 :(得分:1)
也许您可以尝试删除此行?
mFeedListView.setSelectionFromTop(mFirstVisibleItem, mVisibleItemOffset);
修改:您在代码中使用此行两次。
编辑:在您问题的代码中,您只刷新mAdapter而不是mEndlsFidAdptr。那个仍然被分配一个新的。每次为ListView分配一个新的适配器时,它都会滚动回到顶部。
答案 2 :(得分:0)
所以解决方案并不是我正在寻找的合理位置。非常感谢bbrakenhoff指出我正确的方向!
我的类showFeed()是从另一个名为downloadFeed()的类调用的,我的滚动位置没有被维护,因为downloadFeed()在刷新时只加载5个项目,因此即使我保持正确的滚动位置,它也是不可见。
虽然如果其他人有这个问题可能是一个长镜头 - 修复只需创建一个变量来保存用户执行onClick事件时可滚动列表的总大小。然后当再次调用downloadFeed()时,有更多项目要下载而不是默认5.然后,当现在可见项目存在时,可以维护滚动位置。
我最终使用了mFeedListView.setSelectionFromTop(firstVisibleItem,positionOffset)