方向更改后无法删除(子)PreferenceScreen的子项

时间:2012-09-04 21:16:10

标签: android

我有一个OnPreferenceClickListener,应该从Preference删除特定的preference_to_remove(包含密钥PreferenceScreen)。

问题是我的解决方案在preference_to_remove不在嵌套PreferenceScreen内但在包含在嵌套屏幕内并且屏幕方向发生变化时不起作用时有效。在屏幕方向更改之前,嵌套屏幕也按预期工作。

以下代码包含两个版本,一个版本为平面非嵌套PreferenceScreen,另一个版本为嵌套PreferenceScreen

在屏幕方向更改后,嵌套版本无法使用键Preference删除preference_to_remove的原因是什么?除了仅使用平展PreferenceScreensIntents启动新的PreferenceScreens作为伪孩子之外,还有什么解决方案?

PS:我使用PreferenceActivity来兼容FroYo。

如何使用Test-App重现

打开应用程序→单击平面按钮→单击preference_to_click,这将删除preference_to_remove。 →方向更改→单击preference_to_click再次删除preference_to_remove。偏好被删除了吗?成功了!

打开应用程序→单击子屏幕 - 按钮→单击测试→现在重复第一次测试中的步骤,但这次更改方向后preference_to_remove不会被删除。

Download App (Source)

pref_flat.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <Preference
        android:key="preference_to_click"
        android:persistent="false"
        android:title="preference_to_click" />
    <Preference
        android:key="preference_to_remove"
        android:title="preference_to_remove" />

</PreferenceScreen>

pref_subscreen.xml(嵌套的首选项屏幕)

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceScreen
        android:key="subscreen"
        android:persistent="false"
        android:title="Test" >
        <Preference
            android:key="preference_to_click"
            android:persistent="false"
            android:title="preference_to_click" />
        <Preference
            android:key="preference_to_remove"
            android:title="preference_to_remove" />
    </PreferenceScreen>

</PreferenceScreen>

PrefFlatActivity.java和PrefSubscreenActivity.java的差异

1c1
< public class PrefFlatActivity extends PreferenceActivity {
---
> public class PrefSubscreenActivity extends PreferenceActivity {
5,6c5,7
<     public static final String PREFERENCE_TO_CLICK = "preference_to_click";
<     public static final String PREFERENCE_TO_REMOVE = "preference_to_remove";
---
>     private static final String PREFERENCE_TO_CLICK = PrefFlatActivity.PREFERENCE_TO_CLICK;
>     private static final String PREFERENCE_TO_REMOVE = PrefFlatActivity.PREFERENCE_TO_REMOVE;
>     private static final String PREFERENCE_SUBSCREEN = "subscreen";
15c16
<         addPreferencesFromResource(R.xml.pref_flat);
---
>         addPreferencesFromResource(R.xml.pref_subscreen);
28c29
<             PreferenceScreen screen = getPreferenceScreen();
---
>             PreferenceScreen screen = (PreferenceScreen) findPreference(PREFERENCE_SUBSCREEN);

PrefFlatActivity.java(工作)

/**
 * Works as expected. Clicking toggles the "visibility" of the PREFERENCE_TO_REMOVE Preference.
 */
public class PrefFlatActivity extends PreferenceActivity {
    /**
     * Preference keys.
     */
    public static final String PREFERENCE_TO_CLICK = "preference_to_click";
    public static final String PREFERENCE_TO_REMOVE = "preference_to_remove";

    private final String PREF_NAME = getClass().getName() + ".pref";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getPreferenceManager().setSharedPreferencesName(PREF_NAME);
        addPreferencesFromResource(R.xml.pref_flat);

        findPreference(PREFERENCE_TO_CLICK)
            .setOnPreferenceClickListener(new OnFlatClickListener());
    }

    /**
     * Removes or adds Preference with key PREFERENCE_TO_REMOVE when clicked.
     */
    private class OnFlatClickListener implements OnPreferenceClickListener {
        private Preference mRescuedPreference;

        public boolean onPreferenceClick(Preference preference) {
            PreferenceScreen screen = getPreferenceScreen();
            Preference prefToRemove = screen.findPreference(PREFERENCE_TO_REMOVE);

            Log.d("test", "Found PREFERENCE_TO_REMOVE: " + (prefToRemove != null));

            if (prefToRemove != null) {
                screen.removePreference(prefToRemove);
                mRescuedPreference = prefToRemove; // Rescue reference to re-add it later.
            }

            else {
                screen.addPreference(mRescuedPreference);
            }

            return true;
        }
    }
}

PrefSubscreenActivity.java(嵌套,在方向更改后损坏)

/**
 * Broken after orientation change. Clicking does not remove/add PREFERENCE_TO_REMOVE.
 */
public class PrefSubscreenActivity extends PreferenceActivity {
    /**
     * Preference keys.
     */
    private static final String PREFERENCE_TO_CLICK = PrefFlatActivity.PREFERENCE_TO_CLICK;
    private static final String PREFERENCE_TO_REMOVE = PrefFlatActivity.PREFERENCE_TO_REMOVE;
    private static final String PREFERENCE_SUBSCREEN = "subscreen";

    private final String PREF_NAME = getClass().getName() + ".pref";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getPreferenceManager().setSharedPreferencesName(PREF_NAME);
        addPreferencesFromResource(R.xml.pref_subscreen);

        findPreference(PREFERENCE_TO_CLICK)
            .setOnPreferenceClickListener(new OnFlatClickListener());
    }

    /**
     * Removes or adds Preference with key PREFERENCE_TO_REMOVE when clicked.
     */
    private class OnFlatClickListener implements OnPreferenceClickListener {
        private Preference mRescuedPreference;

        public boolean onPreferenceClick(Preference preference) {
            PreferenceScreen screen = (PreferenceScreen) findPreference(PREFERENCE_SUBSCREEN);
            Preference prefToRemove = screen.findPreference(PREFERENCE_TO_REMOVE);

            Log.d("test", "Found PREFERENCE_TO_REMOVE: " + (prefToRemove != null));

            if (prefToRemove != null) {
                screen.removePreference(prefToRemove);
                mRescuedPreference = prefToRemove; // Rescue reference to re-add it later.
            }

            else {
                screen.addPreference(mRescuedPreference);
            }

            return true;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

编辑:我一直无法按照您的要求开始工作。我仔细阅读了Preference s的来源以及它们如何处理状态而没有任何运气,所以我可能遗漏了一些明显的东西(不是经常发生的事情吗?)

我做了一些测试,我相信它用来显示嵌套PreferenceScreen的{​​{1}}和/或Dialog的状态表现得与我们两个都没有预计。例如,使用PreferenceScreen而不是PreferenceCategory时,未遵循此行为。

由于不推荐使用PreferenceScreen这种方式,您可以随时尝试使用片段:

  

http://developer.android.com/reference/android/preference/PreferenceActivity.html

但是,我怀疑你是出于遗留原因而避免这种情况。

另一种选择是以编程方式创建Preference

Building Preference screen in code depending on another setting

或者,您可以自己处理配置更改:

Preference

希望你很快得到这个想法。我确信解决方案最终会在我们身上出现;它不会那么难! 这里希望;)

原始来源(主要)保留在下方:

http://developer.android.com/reference/android/app/Activity.html#ConfigurationChanges
https://stackoverflow.com/questions/3542333/how-to-prevent-custom-views-from-losing-state-across-screen-orientation-changes/8127813#8127813
<activity ..
 android:configChanges="orientation|keyboardHidden" .. >

推荐阅读:http://developer.android.com/guide/topics/resources/runtime-changes.html