[Android] PreferenceFragmentCompatで設定画面を作る
AppCompatActivity + PreferenceFragmentCompatで作る設定画面のサンプルコードです。
完成図
今回扱う内容は
- Fragmentの遷移
- 例としてListPreferenceの定義と適用
です。
コード
詳しいことはコード内のコメントに書きましたので参照ください。
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Buttonクリックで設定画面へ findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, SettingsActivity.class)); } }); } @Override protected void onStart() { super.onStart(); // レイアウトルートの背景をテーマ設定の値によって変更 RelativeLayout root = findViewById(R.id.root); SharedPreferences defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); switch (defaultSharedPreferences.getString("preference_theme", getString(R.string.default_value_preference_theme))) { case "light": root.setBackgroundColor(Color.parseColor("#FFFFFF")); break; case "dark": root.setBackgroundColor(Color.parseColor("#000000")); break; } } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.hatenablog.mnoqlo.sampleapplication.MainActivity"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:gravity="center" android:text="設定画面を開く" /> </RelativeLayout>
SettingsActivity.java
public class SettingsActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); // Toolbarの設定 Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); // savedInstanceStateがnullでない場合は前回のFragmentが自動で復元されるのでnullの場合のみ処理 if (savedInstanceState == null) { // トップ画面のFragmentを表示 getSupportFragmentManager() .beginTransaction() .replace(R.id.fragment_container, SettingsFragment.newInstance("preference_root")) .commit(); } } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { // ActionBarの矢印がクリックされたとき、Backボタンと同等の処理をする // 前のFragmentに戻るのではなくActivity自体を終了させたい場合は代わりに finish(); onBackPressed(); return true; } return super.onOptionsItemSelected(item); } // PreferenceScreenがクリックされた時に呼び出されます @Override public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) { // Fragmentの切り替えと、addToBackStackで戻るボタンを押した時に前のFragmentに戻るようにする getSupportFragmentManager() .beginTransaction() .replace(R.id.fragment_container, SettingsFragment.newInstance(pref.getKey())) .addToBackStack(null) .commit(); return true; } }
activity_settings.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.hatenablog.mnoqlo.sampleapplication.SettingsActivity"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:theme="@style/ToolbarTheme" /> <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/toolbar" /> </RelativeLayout>
SettingsFragment.java
public class SettingsFragment extends PreferenceFragmentCompat { public static SettingsFragment newInstance(String rootKey) { SettingsFragment fragment = new SettingsFragment(); Bundle bundle = new Bundle(); // 第1引数をPreferenceFragmentCompat.ARG_PREFERENCE_ROOTとすることでonCreatePreferencesの第2引数がここでputしたrootKeyになります bundle.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, rootKey); fragment.setArguments(bundle); return fragment; } @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.preferences, rootKey); // クリックされたPreferenceScreen毎にPreferenceのカスタマイズなど switch (rootKey) { case "preference_appearance": onCreateAppearancePreferences(); break; case "preference_others": break; } } private void onCreateAppearancePreferences() { // テーマ設定の現在の値をSummaryに表示 ListPreference themePreference = (ListPreference) findPreference("preference_theme"); themePreference.setSummary(themePreference.getEntry()); themePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { int indexOfValue = themePreference.findIndexOfValue(String.valueOf(newValue)); themePreference.setSummary(indexOfValue >= 0 ? themePreference.getEntries()[indexOfValue] : null); return true; } }); } @Override public void onResume() { super.onResume(); // ActionBarのタイトルに現在表示中のPreferenceScreenのタイトルをセット String rootKey = getArguments().getString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT); getActivity().setTitle(findPreference(rootKey).getTitle()); } }
preferences.xml
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="設定" android:key="preference_root"> <PreferenceScreen android:title="外観設定" android:key="preference_appearance"> <ListPreference android:title="テーマ" android:key="preference_theme" android:entries="@array/entries_preference_theme" android:entryValues="@array/entry_values_preference_theme" android:defaultValue="@string/default_value_preference_theme" /> </PreferenceScreen> <PreferenceScreen android:title="その他の設定" android:key="preference_others"> <PreferenceScreen /> </PreferenceScreen> </PreferenceScreen>
arrays.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="entries_preference_theme"> <item>ライト</item> <item>ダーク</item> </string-array> <string-array name="entry_values_preference_theme"> <item>light</item> <item>dark</item> </string-array> </resources>
strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Sample Application</string> <string name="default_value_preference_theme">light</string> </resources>
styles.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="ToolbarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar"> <item name="android:background">@color/colorPrimary</item> </style> </resources>
build.gradle
/* 省略 */ dependencies { implementation 'androidx.preference:preference:最新バージョン' // 試してはいませんが、AndroidXではなくSupport Libraryの場合は implementation 'com.android.support:preference-v14:最新バージョン' }
androidxの方のバージョンはたぶんここ
Support Libraryの方のバージョンはたぶんここ
間違い等ありましたら、コメントしてくださると助かります🙏🙏
宣伝
Android用Twitterアプリを公開中です。
自動更新(疑似User Streams)やマルチアカウント等の機能に対応しています。
よければお試しください。
無料版
play.google.com
有料版
play.google.com