在我的应用程序中,我有一个派生自ExpandableListActivity的类。 当我滚动内容,然后更改手机方向或编辑项目,然后返回列表时,不保留原始列表位置。 我尝试了两种解决方案,类似于我最近成功使用的ListActivity派生类。
解决方案1:
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
mListState = state.getParcelable(LIST_STATE);
}
protected void onResume() {
super.onResume();
loadData();
if (mListState != null)
getExpandableListView().onRestoreInstanceState(mListState);
}
protected void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
mListState = getExpandableListView().onSaveInstanceState();
state.putParcelable(LIST_STATE, mListState);
}
解决方案2:
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
mListPosition = state.getInt(LIST_STATE);
}
protected void onResume() {
super.onResume();
loadData();
getExpandableListView().setSelection(mListPosition);
}
protected void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
mListPosition = getExpandableListView().getFirstVisiblePosition();
state.putInt(LIST_STATE, mListPosition);
}
两种解决方案都不起作用。我也尝试将两种解决方案结合起来,这在我编辑项目并返回列表时起作用,但是当我改变手机方向时它不起作用
任何人都可以建议一个实现目标的好方法吗?
答案 0 :(得分:21)
经过几次实验后,我得到了一个令人满意的解决方案,它也保留了顶部可见项目的精细滚动位置。
事实上,需要保存和恢复三个不同的信息:列表状态(例如扩展哪些组),第一个可见项的索引及其精细滚动位置。
不幸的是,似乎只有第一个由可扩展列表视图的onSaveInstanceState方法保存,因此其他两个需要单独保存。这与不可扩展的列表视图不同,在该视图中,onSaveInstanceState方法会保存正确恢复列表状态和位置所需的所有信息(关于此主题,请参阅Maintain/Save/Restore scroll position when returning to a ListView)。
以下是代码段;在ExpandableListActivity派生类之上:
private static final String LIST_STATE_KEY = "listState";
private static final String LIST_POSITION_KEY = "listPosition";
private static final String ITEM_POSITION_KEY = "itemPosition";
private Parcelable mListState = null;
private int mListPosition = 0;
private int mItemPosition = 0;
然后,一些覆盖:
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
// Retrieve list state and list/item positions
mListState = state.getParcelable(LIST_STATE_KEY);
mListPosition = state.getInt(LIST_POSITION_KEY);
mItemPosition = state.getInt(ITEM_POSITION_KEY);
}
protected void onResume() {
super.onResume();
// Load data from DB and put it onto the list
loadData();
// Restore list state and list/item positions
ExpandableListView listView = getExpandableListView();
if (mListState != null)
listView.onRestoreInstanceState(mListState);
listView.setSelectionFromTop(mListPosition, mItemPosition);
}
protected void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
// Save list state
ExpandableListView listView = getExpandableListView();
mListState = listView.onSaveInstanceState();
state.putParcelable(LIST_STATE_KEY, mListState);
// Save position of first visible item
mListPosition = listView.getFirstVisiblePosition();
state.putInt(LIST_POSITION_KEY, mListPosition);
// Save scroll position of item
View itemView = listView.getChildAt(0);
mItemPosition = itemView == null ? 0 : itemView.getTop();
state.putInt(ITEM_POSITION_KEY, mItemPosition);
}
这在我的Froyo设备上运行良好。
答案 1 :(得分:6)
这就是我使ExpandableListView.onRestoreInstanceState和onSaveInstanceState工作的方式......
如果您使用的是BaseExpandableListAdapter,则getCombinedChildId的默认实现会返回一个负数。如果您查看从保存的状态滚动位置恢复列表的代码,它会忽略负数的ID。返回正ID,以便AbsListView onRestoreInstanceState正确设置滚动位置。要返回正ID,请通过覆盖BaseExpandableListAdapter子类中的方法将getCombinedChildId或0x8000000000000000L(负数)更改为0x7000000000000000L(正数),如下所示...
public long getCombinedChildId(long groupId, long childId)
{
long or = 0x7000000000000000L;
long group = (groupId & 0x7FFFFFFF) << 32;
long child = childId & 0xFFFFFFFF;
return or | group | child;
}
答案 2 :(得分:0)
我发现另一种方法可以帮助我维持状态。这是链接。
http://markmail.org/message/msesxums77bdoqnx#query:+page:1+mid:utmart4ob7flh3u7+state:results
总结是你总是要设置状态,即使convertView!= null。
我不知道总是设置状态的影响,但在我看来它完美无缺。
答案 3 :(得分:-2)
要在更改手机方向时阻止重新加载您的活动,只需将以下行添加到活动部分的AndroidManifest.xml中:
android:configChanges="keyboardHidden|orientation|screenSize"