问题解决了
随着这个问题变得多么流行,我决定再次重新审视这个问题,看看我是否能找到解决方案......我做到了。找到了一个不错的小工作,解决了单窗格显示而不是双窗格的问题,并确保在双窗格模式下始终预先选择标题。
如果您不关心解释,则可以跳到代码。如果您不关心 ICS,则可以删除许多标头跟踪代码,因为 JB 为标头数组列表添加了 getter。
双窗格问题
在单窗格模式或双窗格模式下查看首选项标题列表时,只会创建一个首选项活动,并且对于这两种情况,它是相同的活动。因此,在处理将切换窗格模式的屏幕旋转时永远不会有问题。
但是,在单窗格模式下,当您单击标题时,相应的片段将附加到 NEW 首选项活动。这个包含 PreferredActivity 的新片段从不调用 。为什么会这样呢?它不需要显示它们。这就是问题所在。onBuildHeaders()
将该片段旋转到双窗格模式时,它没有任何要显示的标题列表,因此它只是继续仅显示片段。即使它确实显示了标头的列表,您也会遇到一些反向堆栈问题,因为您现在将有两个显示标头的PpreferencesActivity副本。继续点击足够的标题,您将获得相当长的一堆活动供用户导航回来。因此,答案很简单。只是活动。然后,它将加载具有标题列表的原始首选项活动,并将正确显示双窗格模式。finish()
自动选择标头
需要解决的下一个问题是,使用新修复在单窗格模式到双窗格模式之间切换不会自动选择标头。您只剩下一个标头列表,并且没有加载任何详细信息片段。此修复程序并不那么简单。基本上,您只需要跟踪上次单击的标题,并确保在首选项创建期间...始终选择标题。
这在 ICS 中最终有点烦人,因为 API 不会公开内部跟踪的标头列表的 getter。Android确实已经保留了该列表,您可以从技术上使用相同的私人存储的内部字符串密钥来检索它,但这只是一个糟糕的设计选择。相反,我建议自己再次手动保存它。
如果您不关心ICS,那么您可以只使用JB中公开的方法,而不必担心任何这些保存/恢复状态的东西。getHeaders()
法典
public class SettingsActivity extends PreferenceActivity {
private static final String STATE_CUR_HEADER_POS = "Current Position";
private static final String STATE_HEADERS_LIST = "Headers List";
private int mCurPos = AdapterView.INVALID_POSITION; //Manually track selected header position for dual pane mode
private ArrayList<Header> mHeaders; //Manually track headers so we can select one. Required to support ICS. Otherwise JB exposes a getter instead.
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference, target);
mHeaders = (ArrayList<Header>) target; //Grab a ref of the headers list
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//This is the only code required for ensuring a dual pane mode shows after rotation of a single paned preference screen
if (onIsMultiPane() && onIsHidingHeaders()) {
finish();
}
}
@Override
public boolean onIsMultiPane() {
//Override this if you want dual pane to show up on smaller screens
return getResources().getBoolean(R.bool.pref_prefer_dual_pane);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
//Intercept a header click event to record its position.
mCurPos = position;
}
@Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
//Retrieve our saved header list and last clicked position and ensure we switch to the proper header.
mHeaders = state.getParcelableArrayList(STATE_HEADERS_LIST);
mCurPos = state.getInt(STATE_CUR_HEADER_POS);
if (mHeaders != null) {
if (mCurPos != AdapterView.INVALID_POSITION) {
switchToHeader(mHeaders.get(mCurPos));
} else {
switchToHeader(onGetInitialHeader());
}
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Persist our list and last clicked position
if (mHeaders != null && mHeaders.size() > 0) {
outState.putInt(STATE_CUR_HEADER_POS, mCurPos);
outState.putParcelableArrayList(STATE_HEADERS_LIST, mHeaders);
}
}
}