简体   繁体   English

PreferenceScreen 未在方向更改时恢复

[英]PreferenceScreen not being restored on orientation change

I had the following (minor but nagging:) problem: I've got a PreferenceActivity with a XML preference hierarchy definition with "sub PreferenceScreens ", ie several PreferenceScreens under the top level PreferenceScreen , and when the user clicks them, a sub hierarchy of other preferences is being displayed.我有以下(次要但烦人的:)问题:我有一个PreferenceActivity ,其 XML 首选项层次结构定义为“sub PreferenceScreens ”,即顶层PreferenceScreens PreferenceScreen当用户单击它们时,子层次结构为正在显示其他首选项。

If I have displayed such a sub PreferenceScreen and the orientation is being changed from portrait to landscape or vice versa, the main PreferenceScreen is displayed afterwards.如果我已经显示了这样一个PreferenceScreen并且方向正在从纵向更改为横向或反之亦然,则随后会显示PreferenceScreen Which means: The preference hierarchy state was not being restored properly.这意味着:首选项层次结构 state 未正确恢复。 I would expect the sub PreferenceScreen to be displayed after the orientation change, just as before the orientation change.我希望PreferenceScreen在方向更改之后显示,就像在方向更改之前一样。

Now I found out that the problem can be solved by assigning any random key (eg "dummy") to the sub PreferenceScreen .现在我发现可以通过将任何随机密钥(例如“虚拟”)分配给子PreferenceScreen来解决问题。 Which does not make any sense!这没有任何意义! Why would a PreferenceScreen ever need a key (except as a workaround for the above problem)?为什么PreferenceScreen需要一个密钥(除了作为上述问题的解决方法)?

My actual question: Is this behaviour a bug in the framework class(es)?我的实际问题:这种行为是框架类中的错误吗? If not: Can someone explain me how that makes sense?如果不是:有人可以解释一下这有什么意义吗?

My example code:我的示例代码:

HelloAndroid.java:你好Android.java:

public class HelloAndroid extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Button view = new Button(this);
        view.setText("Start Preference");
        final Context ctx = this;
        view.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                startActivity(new Intent(ctx, HelloPreferenceActivity.class));
            }
        });
        this.setContentView(view);
    }

HelloPreferenceActivity.java:你好PreferenceActivity.java:

public class HelloPreferenceActivity extends PreferenceActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
    }
}

preference.xml:首选项.xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference android:key="examplePref"
        android:title="ExamplePref">
    </CheckBoxPreference>
    <PreferenceScreen android:title="SubScreen..."
        android:key="dummy"> <!-- works with, does not work without this key -->
        <CheckBoxPreference android:key="exPrefSubScreen"
            android:title="ExPrefSubScreen">
        </CheckBoxPreference>
    </PreferenceScreen>
</PreferenceScreen>

This is by design, the state of Preference is associated with its key.这是设计使然, Preference的 state 与其密钥相关联。 If Preference has no key then it will not be able to save/restore its state.如果 Preference 没有密钥,那么它将无法保存/恢复其 state。

The similar behavior can be found in views withing layouts.在带有布局的视图中可以找到类似的行为。 If view has no id specified for it, it will not be able to restore state after configuration change.如果视图没有为其指定id ,则配置更改后将无法恢复 state。

And to back my words up, here is an example of how Preference saves its state :为了支持我的话,这里是Preference如何保存其 state的示例:

void dispatchSaveInstanceState(Bundle container) {
    if (hasKey()) {
        mBaseMethodCalled = false;
        Parcelable state = onSaveInstanceState();
        if (!mBaseMethodCalled) {
            throw new IllegalStateException(
                    "Derived class did not call super.onSaveInstanceState()");
        }
        if (state != null) {
            container.putParcelable(mKey, state);
        }
    }
}

And here is how Preference tries to restore its state :以下是Preference如何尝试恢复其 state

void dispatchRestoreInstanceState(Bundle container) {
    if (hasKey()) {
        Parcelable state = container.getParcelable(mKey);
        if (state != null) {
            mBaseMethodCalled = false;
            onRestoreInstanceState(state);
            if (!mBaseMethodCalled) {
                throw new IllegalStateException(
                        "Derived class did not call super.onRestoreInstanceState()");
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM