Posted at

【Android】便利なPreferenceFragmentCompatで設定画面を作る


Jetpack Preference

公式ページ

JetpackのPreferenceを使う事で、設定画面を簡単に作成する事ができる。


:computer:環境構築


app/build.gradle に以下を追加

dependencies {

implementation 'androidx.preference:preference:1.0.0'
}


:pencil: 実装



簡単なサンプル



  1. まずは設定の項目を定義した、res/xml/preferences.xml を以下の内容で作成する

    <androidx.preference.PreferenceScreen
    
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <SwitchPreferenceCompat
    app:key="notifications"
    app:title="Enable message notifications"/>

    <Preference
    app:key="feedback"
    app:title="Send feedback"
    app:summary="Report technical issues or suggest new features"/>

    </androidx.preference.PreferenceScreen>

    ※ xmlのルートが PreferenceScreen になっている事に注意




  2. 次に PreferenceFragmentCompat を継承したFragmentを作成


    SettingsFragment.kt

    class SettingsFragment : PreferenceFragmentCompat() {

    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    setPreferencesFromResource(R.xml.preferences, rootKey)
    }
    }


    setPreferencesFromResource で定義した res/xml/preferences.xml を設定




  3. 土台となるActivityで作成した SettingsFragment を表示する


    SettingsActivity.kt

    class SettingsActivity : RxAppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_settings)

    supportFragmentManager
    .beginTransaction()
    .replace(R.id.settingsContainer, SettingsFragment())
    .commit()
    }
    }


    レイアウトファイルにはFragmentが表示される FrameLayout を定義


    res/layout/activity_settings.xml

    <?xml version="1.0" encoding="utf-8"?>
    
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.Toolbar
    android:id="@+id/settingsToolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimaryDark"
    app:titleTextColor="@android:color/white"/>

    <FrameLayout
    android:id="@+id/settingsContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/settingsToolbar"/>

    </RelativeLayout>




上記まで実装したら、一度実行してみる。

image.png (40.2 kB)

res/xml/preferences.xml で定義した内容が表示されていればOK


SharedPreferenceファイル名

作成されるSharedPreferenceファイル名は

"${BuildConfig.APPLICATION_ID}_preferences"

となる。


Preferenceの種類

一覧はこちら


  • Preference


    • 基本的な構成要素で対応するキーと値のペアを持つ



  • EditTextPreference


    • String値を保持するPreference、入力欄がテキストフィールドで表示される



  • ListPreference


    • String値を保持するPreference、入力欄がラジオボタンのリストで表示される



  • MultiSelectListPreference


    • 一連の文字列を永続化する設定、入力欄がラベル付きチェックボックスのリストで表示される



  • SeekBarPreference


    • 整数値を保持する設定、入力欄がシークバーで表示される



  • SwitchPreferenceCompat


    • ブール値を保持する設定、入力欄がスイッチで表示される



  • CheckBoxPreference


    • ブール値を保持する設定、入力欄がチェックボックスで表示される




:raised_hands: SharedPreferencesに保存された時に何かしたい場合


SharedPreferences.OnSharedPreferenceChangeListenerを使う

SharedPreferences#registerOnSharedPreferenceChangeListener でlistenerを登録。

※ 上記を無名関数でやっちゃうと上手く動かないので注意 こちら参照

PreferenceFragmentCompatが終了するタイミングで登録解除する

SharedPreferences#unregisterOnSharedPreferenceChangeListener

    var sharedPreferences: SharedPreferences? = null

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)

context?.also {
// SharedPreferencesを取得しOnSharedPreferenceChangeListenerを設定
sharedPreferences = it.getSharedPreferences("xxxxxxxxx", Context.MODE_PRIVATE).apply {
registerOnSharedPreferenceChangeListener(changeListener)
}
}
}

override fun onDestroy() {
super.onDestroy()
context?.also {
// OnSharedPreferenceChangeListenerの登録解除
sharedPreferences?.unregisterOnSharedPreferenceChangeListener(changeListener)
}
}

private val changeListener = SharedPreferences.OnSharedPreferenceChangeListener { pref, key ->
// do something
}


:link: 関連リンク