我有PreferenceFragment
,用于更改多个不同项目的相同设置。显然,不同的项目需要使用不同的密钥存储首选项值。所以我在创建片段后更改了所有首选项的键。
首选项通常由xml定义:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="_key_one"
android:title="Title of first preference" />
[... and more Preferences]
</PreferenceScreen>
我更改密钥的PreferenceFragment:
public class ItemSettingPreferenceFragment extends PreferenceFragment {
private String mItemKey;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mItemKey = getArguments().getString('item_key'); //this will contain name of item
addPreferencesFromResource(R.xml.item_settings_preferences);
for (int i=0; i< getPreferenceScreen().getPreferenceCount(); i++){
final Preference pref = getPreferenceScreen().getPreference(i);
pref.setKey(mItemKey + pref.getKey());
}
}
}
现在所有首选项都为每个项目都有一个唯一的键,例如“item1_key_one”
不幸的是,在创建之后,这些首选项会加载并使用原始密钥“_key_one”
如何强制首选项重新加载新密钥的值并显示这些值?
答案 0 :(得分:3)
据我所知,“key”就像你的偏好的“id”,这意味着你不能在创建后更改首选项“key”。如果您需要动态生成首选项,那么您可能不应该在XML中定义首选项。
以下是来自android示例API的示例,演示了如何从代码而不是从XML生成首选项。
public class PreferencesFromCode extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setPreferenceScreen(createPreferenceHierarchy());
}
private PreferenceScreen createPreferenceHierarchy() {
// Root
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);
// Inline preferences
PreferenceCategory inlinePrefCat = new PreferenceCategory(this);
inlinePrefCat.setTitle(R.string.inline_preferences);
root.addPreference(inlinePrefCat);
// Checkbox preference
CheckBoxPreference checkboxPref = new CheckBoxPreference(this);
checkboxPref.setKey("checkbox_preference");
checkboxPref.setTitle(R.string.title_checkbox_preference);
checkboxPref.setSummary(R.string.summary_checkbox_preference);
inlinePrefCat.addPreference(checkboxPref);
// Switch preference
SwitchPreference switchPref = new SwitchPreference(this);
switchPref.setKey("switch_preference");
switchPref.setTitle(R.string.title_switch_preference);
switchPref.setSummary(R.string.summary_switch_preference);
inlinePrefCat.addPreference(switchPref);
// Dialog based preferences
PreferenceCategory dialogBasedPrefCat = new PreferenceCategory(this);
dialogBasedPrefCat.setTitle(R.string.dialog_based_preferences);
root.addPreference(dialogBasedPrefCat);
// Edit text preference
EditTextPreference editTextPref = new EditTextPreference(this);
editTextPref.setDialogTitle(R.string.dialog_title_edittext_preference);
editTextPref.setKey("edittext_preference");
editTextPref.setTitle(R.string.title_edittext_preference);
editTextPref.setSummary(R.string.summary_edittext_preference);
dialogBasedPrefCat.addPreference(editTextPref);
// List preference
ListPreference listPref = new ListPreference(this);
listPref.setEntries(R.array.entries_list_preference);
listPref.setEntryValues(R.array.entryvalues_list_preference);
listPref.setDialogTitle(R.string.dialog_title_list_preference);
listPref.setKey("list_preference");
listPref.setTitle(R.string.title_list_preference);
listPref.setSummary(R.string.summary_list_preference);
dialogBasedPrefCat.addPreference(listPref);
// Launch preferences
PreferenceCategory launchPrefCat = new PreferenceCategory(this);
launchPrefCat.setTitle(R.string.launch_preferences);
root.addPreference(launchPrefCat);
/*
* The Preferences screenPref serves as a screen break (similar to page
* break in word processing). Like for other preference types, we assign
* a key here so that it is able to save and restore its instance state.
*/
// Screen preference
PreferenceScreen screenPref = getPreferenceManager().createPreferenceScreen(this);
screenPref.setKey("screen_preference");
screenPref.setTitle(R.string.title_screen_preference);
screenPref.setSummary(R.string.summary_screen_preference);
launchPrefCat.addPreference(screenPref);
/*
* You can add more preferences to screenPref that will be shown on the
* next screen.
*/
// Example of next screen toggle preference
CheckBoxPreference nextScreenCheckBoxPref = new CheckBoxPreference(this);
nextScreenCheckBoxPref.setKey("next_screen_toggle_preference");
nextScreenCheckBoxPref.setTitle(R.string.title_next_screen_toggle_preference);
nextScreenCheckBoxPref.setSummary(R.string.summary_next_screen_toggle_preference);
screenPref.addPreference(nextScreenCheckBoxPref);
// Intent preference
PreferenceScreen intentPref = getPreferenceManager().createPreferenceScreen(this);
intentPref.setIntent(new Intent().setAction(Intent.ACTION_VIEW)
.setData(Uri.parse("http://www.android.com")));
intentPref.setTitle(R.string.title_intent_preference);
intentPref.setSummary(R.string.summary_intent_preference);
launchPrefCat.addPreference(intentPref);
// Preference attributes
PreferenceCategory prefAttrsCat = new PreferenceCategory(this);
prefAttrsCat.setTitle(R.string.preference_attributes);
root.addPreference(prefAttrsCat);
// Visual parent toggle preference
CheckBoxPreference parentCheckBoxPref = new CheckBoxPreference(this);
parentCheckBoxPref.setTitle(R.string.title_parent_preference);
parentCheckBoxPref.setSummary(R.string.summary_parent_preference);
prefAttrsCat.addPreference(parentCheckBoxPref);
// Visual child toggle preference
// See res/values/attrs.xml for the <declare-styleable> that defines
// TogglePrefAttrs.
TypedArray a = obtainStyledAttributes(R.styleable.TogglePrefAttrs);
CheckBoxPreference childCheckBoxPref = new CheckBoxPreference(this);
childCheckBoxPref.setTitle(R.string.title_child_preference);
childCheckBoxPref.setSummary(R.string.summary_child_preference);
childCheckBoxPref.setLayoutResource(
a.getResourceId(R.styleable.TogglePrefAttrs_android_preferenceLayoutChild,
0));
prefAttrsCat.addPreference(childCheckBoxPref);
a.recycle();
return root;
}
}
在创建首选项之前,您将能够 setKey()。
答案 1 :(得分:2)
在阅读完所有相关的Preference类之后,我找到了一个简单的解决方案。由于没有允许重新加载首选项的公共方法,我必须使用反射
我必须调用的必要方法protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue)
在Preference.class
内找到或被任何子类覆盖。
因为我不知道哪个超类实现了这个方法,所以我必须迭代所有的超类并尝试查找并调用该方法,直到成功为止。
public class ItemSettingPreferenceFragment extends PreferenceFragment {
private String mItemKey;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mItemKey = getArguments().getString('item_key'); //this will contain name of item
addPreferencesFromResource(R.xml.item_settings_preferences);
for (int i=0; i< getPreferenceScreen().getPreferenceCount(); i++){
Preference pref = getPreferenceScreen().getPreference(i);
pref.setKey(mItemKey + pref.getKey());
Class iterClass = pref.getClass();
while(iterClass != Object.class) {
try {
Method m = iterClass.getDeclaredMethod("onSetInitialValue", boolean.class, Object.class);
m.setAccessible(true);
m.invoke(pref, true, null);
} catch (Exception e) { }
iterClass = iterClass.getSuperclass();
}
}
}
}
它可能不是最高性能的解决方案,但它适用于我的情况。
答案 2 :(得分:0)
最简单的解决方案是使用单独的设置名称:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getPreferenceManager().setSharedPreferencesName("MyPrefs_" + someSufix);
addPreferencesFromResource(R.xml.pref_my);
}
而不是为键值添加前缀。