2013-07-14 38 views
2

我有一個PreferenceFragment這是用來改變幾個不同的項目相同的設置。顯然,不同的項目需要使用不同的密鑰存儲首選項值。所以我在創建片段後更改所有首選項的關鍵。Android:如何在更改密鑰後刷新顯示的首選項?

首由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」顯示值

如何強制首選項重新加載新密鑰的值並顯示這些值?

回答

2

讀完所有相關的偏好類後,我找到了一個簡單的解決方案。由於沒有允許重新加載偏好的公開方法,我必須使用反思。
我必須撥打的必要方法是在Preference.class內找到的protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue)或被任何子類覆蓋。
因爲我不知道哪個超類實現了這個方法,所以我必須遍歷所有的超類,並嘗試查找並調用該方法,直到成功。

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(); 
      } 
     } 
    } 
} 

它可能不是最高性能的解決方案,但它適用於我的情況。

3

據我所知,一個「鑰匙」就像你的喜好的「ID」,這意味着你不能改變它的創建後的首選項「鑰匙」。如果您需要動態生成首選項,那麼您可能不應該在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的()創建偏好之前。

+0

謝謝,我希望避免這種情況,因爲我希望項目結構清晰,即在相同的地方都有明確的偏好。此外,我使用一些自創的首選項,這些首選項僅用於XML - 它們的屬性沒有任何Setters - 看起來我必須擴展它們: - / – Jantlem

0

最省事的辦法是使用單獨的設置名稱:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    getPreferenceManager().setSharedPreferencesName("MyPrefs_" + someSufix); 
    addPreferencesFromResource(R.xml.pref_my); 
} 

,而不是前綴鍵值。

相關問題