我有一个很长的ListView,用户可以在返回前一个屏幕之前滚动它。当用户再次打开这个ListView时,我希望列表被滚动到与之前相同的位置。关于如何实现这一点,你有什么想法吗?
当前回答
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);
}
}
}
这就够了
其他回答
If you are saving/restoring scroll position of ListView yourself you are essentially duplicating the functionality already implemented in android framework. The ListView restores fine scroll position just well on its own except one caveat: as @aaronvargas mentioned there is a bug in AbsListView that won't let to restore fine scroll position for the first list item. Nevertheless the best way to restore scroll position is not to restore it. Android framework will do it better for you. Just make sure you have met the following conditions:
确保你没有调用setSaveEnabled(false)方法,也没有为xml布局文件中的列表设置android:saveEnabled="false"属性 为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标签)方法获取片段。 确保ListView有一个唯一的android:id。
To avoid aforementioned caveat with first list item you can craft your adapter the way it returns special dummy zero pixels height view for the ListView at position 0. Here is the simple example project shows ListView and ExpandableListView restore their fine scroll positions whereas their scroll positions are not explicitly saved/restored. Fine scroll position is restored perfectly even for the complex scenarios with temporary switching to some other application, double screen rotation and switching back to the test application. Please note, if you are explicitly exiting the application (by pressing the Back button) the scroll position won't be saved (as well as all other Views won't save their state). https://github.com/voromto/RestoreScrollPosition/releases
为了澄清Ryan Newsom的精彩回答并针对片段进行调整通常情况下,我们想要从主ListView片段导航到细节片段然后再返回主ListView片段
private View root;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
if(root == null){
root = inflater.inflate(R.layout.myfragmentid,container,false);
InitializeView();
}
return root;
}
public void InitializeView()
{
ListView listView = (ListView)root.findViewById(R.id.listviewid);
BaseAdapter adapter = CreateAdapter();//Create your adapter here
listView.setAdpater(adapter);
//other initialization code
}
这里的“神奇”是,当我们从细节片段导航回ListView片段时,视图不会被重新创建,我们不设置ListView的适配器,所以一切都保持不变!
我发布这篇文章是因为我很惊讶没有人提到这一点。
当用户单击返回按钮后,他将返回到列表视图,在相同的状态,因为他离开它。
这段代码将覆盖“向上”按钮的行为与后退按钮相同,所以在Listview ->细节->回到Listview(没有其他选项)的情况下,这是最简单的代码来维护滚动位置和Listview中的内容。
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return(true);
}
return(super.onOptionsItemSelected(item)); }
注意:如果你可以从细节活动转到另一个活动,向上按钮将返回到该活动,所以你必须操作后退按钮历史,以使其工作。
我发现了一些有趣的事情。
我尝试了setSelection和scrolltoXY,但它根本不起作用,列表仍然在相同的位置,经过一些尝试和错误,我得到了以下代码,确实工作
final ListView list = (ListView) findViewById(R.id.list);
list.post(new Runnable() {
@Override
public void run() {
list.setSelection(0);
}
});
如果不是发布Runnable,你尝试runOnUiThread,它也不工作(至少在一些设备上)
这是一个非常奇怪的变通方法,应该是直截了当的。
我采用了@(Kirk Woll)建议的解决方案,它对我很有效。我还在“联系人”应用程序的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设备上,当你改变手机方向时,当你编辑一个项目并返回列表时,这都是有效的。