Android
android開発
Preference

【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: 関連リンク