phicdy devlog

Androidアプリ開発やその他技術系の記事をたまに書きます

AndroidとかiOSとかモバイル多め。その他技術的なことも書いていきます。

【Android】PreferenceActivity/PreferenceFragmentを使った設定画面

(追記) 2018/11/15 書き直しました。

phicdy.hatenablog.com

Androidの設定画面について

  • AndroidではAPI1から設定画面を生成してくれるPreferenceActivityが用意されている
  • Android 3.0で各設定画面をFragmentに分けるためのPreferenceFragmentが追加された
  • Android 4.0ではPreferenceActivityが拡張され、PreferenceFragmentと組み合わせることでハンドセットでは1画面、タブレットでは2画面の設定画面を自動的に作成できる

設定項目

クラス 説明
CheckBoxPreference オン/オフの設定項目
SwitchPreference オン/オフの設定項目
API14から
ListPreference リストの中から1つ選ぶ設定項目
MultiSelectListPreference リストの中から複数を選ぶ設定項目
EditTextPreference 入力からの設定

1画面の設定画面

  • 設定画面を2ページに分けない場合は、画面のルートに当たるandroid.R.id.contentに直接PreferenceFragmentを設定する

PreferenceActivity

public class SettingActivity extends PreferenceActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getFragmentManager().beginTransaction()
            .replace(android.R.id.content, new SettingFragment())
            .commit();
    }
}

PreferenceFragment

  • addPreferencesFromResource()で設定画面を定義したXMLを読み込む
  • 必要であれば、onActivityCreated()で各設定項目の初期値等を設定する
  • XMLで設定したPreferenceを取得するにはandroid:keyを使い、PreferenceFragment#findPreference()で行う
public class SettingFragment extends PreferenceFragment {

    public SettingFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.setting_fragment);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initView();
    }

    private void initView() {
        ListPreference listPreference = (ListPreference)findPreference(getString(R.string.key_list_preference));
        listPreference.setValueIndex(0);
    }

}

PreferenceFragmentから読み込む設定XML

  • PreferenceFragmentから読み込むXMLのトップはPreferenceScreenでなければならない
  • 各Preferenceにはandroid:keyを設定しなければならない。これが各Preferenceを特定するIDとなる。
  • カテゴリを設定する場合はPreferenceCategoryを使う。android:keyは必須ではない。
  • ListPreferenceの場合、選択候補に表示されるリスト(android:entries)と実際の値のリスト(android:entryValues)を設定する必要がある
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
    <PreferenceCategory android:title="Category Title" >
        <ListPreference
            android:title="Title"
            android:key="@string/key_list_preference"
            android:entries="@array/entry_sample"
            android:entryValues="@array/entry_sample_values"/>
    </PreferenceCategory>

</PreferenceScreen>

その他の属性は以下を参照

http://developer.android.com/reference/android/preference/Preference.html

array.xml

ListPreferenceで使う値を定義する

<resources>
    <array name="entry_sample">
        <item>@string/entry1</item>
        <item>@string/entry2</item>
    </array>

    <string-array name="entry_sample_values">
        <item>1</item>
        <item>0</item>
    </string-array>

</resources>

string.xml

  • android:keyに使う文字列はXMLとPreferenceFragmentで共有するので、string.xmlに定義しておく
<resources>
    <string name="entry1">Entry1</string>
    <string name="entry2">Entry2</string>
    <string name="key_list_preference">KeyListPreference</string>
</resources> 

初期値設定

XMLで初期値を設定する場合はandroid:defaultValueに設定する。SharedPreferenceから保存した値を読み込んでそれに応じて初期値を設定する場合など、Javaコードの中で初期値を設定を行う場合はPreferenceによって設定方法が異なる

SwitchPreference

setChecked()で行う

SwitchPreference switchPref = (SwitchPreference)findPreference(getString(R.string.key_internal_browser));
switchPref.setChecked(true);

ListPreference

  • ListPreferenceのentryValuesのstring-arrayの各itemが数字だとsetDefaultValue()が動かなかった
  • setValueIndex()を使うことで解決
  • entryValuesをinterger-arrayにするとNullPointerExceptionで落ちてしまう

参考