我有一个 OnPreferenceClickListener
,它应该从 PreferenceScreen
中删除特定的 Preference
(使用键 preference_to_remove
)。
问题是,当 preference_to_remove
不在嵌套的 PreferenceScreen
内时,我的解决方案有效,但当它在嵌套的屏幕内并且屏幕方向发生变化时,我的解决方案不起作用.在屏幕方向更改之前,嵌套屏幕也按预期工作。
以下代码包含两个版本,一个带有扁平的非嵌套 PreferenceScreen
和损坏的嵌套 PreferenceScreen
。
在屏幕方向更改后,嵌套版本无法使用键 preference_to_remove
删除 Preference
的原因是什么?除了仅使用平面 PreferenceScreens
和 Intents
来启动新的 PreferenceScreens
作为伪子项之外,还有什么解决方案?
PS:我正在使用 PreferenceActivity
来实现 FroYo 兼容性。
如何使用 Test-App 重现
打开应用 → 点击 Flat-Button → 点击 preference_to_click
应该移除 preference_to_remove
。 → 方向更改 → 单击 preference_to_click
再次删除 preference_to_remove
。偏好被移除?成功!
打开 App → 点击 Subscreen-Button → 点击 Test → 现在重复第一次测试的步骤,但是这次 preference_to_remove
不会在方向改变后不可移除。
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(嵌套 PreferenceScreen)
<?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;
}
}
}
最佳答案
编辑:我一直无法按照您的要求让它工作。我通读了 Preference
的源代码以及它们如何处理状态但没有任何运气,所以我可能遗漏了一些明显的东西(这不是经常发生的事情吗?)
我做了一些测试,我相信 PreferenceScreen
和/或用于显示嵌套 PreferenceScreen
的 Dialog
的状态以我们双方都没有预料到的方式行事。例如,当使用 PreferenceCategory
而不是 PreferenceScreen
时,不会观察到此行为。
由于这种使用 Preference
的方式已被弃用,您可以随时尝试使用 fragment :
http://developer.android.com/reference/android/preference/PreferenceActivity.html
但是,我怀疑您是出于遗留原因而避免这样做。
另一种选择是以编程方式创建您的Preference
:
Building Preference screen in code depending on another setting
或者,您可以自己处理配置更改:
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" .. >
希望您能尽快解决这个问题。我相信解决方案最终会出现在我们面前;不可能那么难! 这是希望 ;)
原始来源(大部分)保留在下面:
package com.example.removepref;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.util.Log;
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
protected void onResume() {
super.onResume();
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;
private boolean mPrefToRemoveVisible = true;
public boolean onPreferenceClick(Preference preference) {
// toggle visibility
mPrefToRemoveVisible = !mPrefToRemoveVisible;
PreferenceScreen screen = (PreferenceScreen) findPreference(PREFERENCE_SUBSCREEN);
Preference prefToRemove = screen.findPreference(PREFERENCE_TO_REMOVE);
Log.d("test", "Found PREFERENCE_TO_REMOVE: " + (prefToRemove != null));
Log.d("test", "And noted mPrefToRemoveVisible: " + mPrefToRemoveVisible);
//Replaced the conditional blocks:
if (mPrefToRemoveVisible && null == prefToRemove) {
boolean added = screen.addPreference(mRescuedPreference);
Log.d("test", "screen.addPreference(mRescuedPreference) success?" + added);
} else if (!mPrefToRemoveVisible && null != prefToRemove) {
mRescuedPreference = prefToRemove;
boolean removed = screen.removePreference(prefToRemove);
Log.d("test", "screen.removePreference(mRescuedPreference) success?" + removed);
}
return true;
}
}
}
推荐阅读:http://developer.android.com/guide/topics/resources/runtime-changes.html
关于android - 方向更改后无法删除(子)PreferenceScreen 的子级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12271475/