tl;dr
xmlでPreferenceを定義すると、リストの項目とかをあらかじめ定義しないといけなくなります。
DBからリストの値を取ってきたいとか、動的にリストの項目を変える方法の備忘録。
Preferenceを新規追加するとき
class AddPreferenceFragment : PreferenceFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
addPreferencesFromResource(R.xml.add_pref)
val programmableEntries = arrayOf("サル", "ゴリラ", "チンパンジー")
preferenceScreen.addPreference(ListPreference(this.activity).apply {
title = "追加されたヤツ"
key = "key_added_pref"
dialogTitle = "ダイアログのタイトル"
setDefaultValue("最初から設定されてるヤツ")
entries = programmableEntries
entryValues = programmableEntries
})
}
preferenceScreenを取得した後に、addPrefenreceするだけです。
リストの項目をentriesとentryValuesでセットします。
xmlで記述するときは
titleを設定するとダイアログにも同じタイトルが出るのですが、
コード上でpreferenceを作る場合は、dialogTitleを設定してやらないと出ないようです。
既存のPreferenceの値を変えるとき
class ReplacePreferenceFragment : PreferenceFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
addPreferencesFromResource(R.xml.add_pref)
val programmableEntries = arrayOf("サル", "ゴリラ", "チンパンジー")
findPreference(getString(R.string.key_pref_replace)) as? SelectListPreference)?.apply {
entries = programmableEntries
entryValues = programmableEntries
})
}
こちらはfindPreferenceでxmlに予め設定してあるkeyからpreferenceを取得します。
findPreferenceはfindViewByIdと同じようにPreferenceの基底クラスで返されるので、キャストしてあげる。
あとは同じようにentriesとentryValuesでセットするだけ。
ポイントとか
最初にaddPreferenceFromResourceを呼ぶ
最初にどのxmlからPreferenceを取得しているかを知る必要があるので、
preferenceScreenやfindPrefenreceを呼ぶ前に
addPreferenceFromResourceを呼んでください。
MultiListPreferenceを使う場合
defaultValueを設定する場合は、Array型ではなく、Set型にする必要があるのでお忘れなく。
addPrefenreceのPrefereceに渡すContextはactivityで
この記事のコードもPreferenceを追加するときに
preferenceScreen.addPreference(ListPreference(this.activity)
とactivityを渡してますが、これにApplicationContextとかBaseContextとか渡しても、
これらのContextは画面に関する情報を持ってないのでDialogの生成ができずに、
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
とかで落ちます。