PreferenceFragment で RadioButton を実現する
Android の設定画面に表示した項目の一覧から項目を一つ選択したい。
例: アカウント一覧からアカウントを選択したい場合など。
Android Framework の Preference 関連のクラスには RadioButton が用意されていないので下記の実装が必要になる。
雛形作成
Eclipse で Android 4.0.3(API Level: 15)以上を対象にした Android プロジェクトを新規作成する。
Android プロジェクトには、1つの PreferenceMainActivity の継承クラスと1つの PreferenceFragment の継承クラスが含まれる。
雛形 Eclipse プロジェクトは、下記の GitHub URL を参照のこと。
Account 一覧を表示
DB(にあると仮定する)からアカウント情報を読み込んで PreferenceFragment に追加する。
アカウント情報1件ごとに CheckBoxPreference のインスタンスを生成して親の PreferenceScreen に追加する。
public class PreferenceAccountFragment extends PreferenceFragment {
private PreferenceScreen mRootPreferenceScreen;
private String mSelectAccount;
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRootPreferenceScreen = getPreferenceManager().createPreferenceScreen(getActivity());
setPreferenceScreen(mRootPreferenceScreen);
}
@Override
public void onResume() {
super.onResume();
loadSelectAccount();
removeAllPreferenceScreen();
buildAccountsPreferences();
}
private void removeAllPreferenceScreen() {
mRootPreferenceScreen.removeAll();
}
private void buildAccountsPreferences() {
for (final String account : Constants.ACCOUNTS) {
final Preference preference = buildAccountPreferences(account);
mRootPreferenceScreen.addPreference(preference);
}
}
private Preference buildAccountPreferences(final String account) {
final CheckBoxPreference p = new CheckBoxPreference(getActivity());
p.setTitle(account);
final boolean isChecked = TextUtils.equals(mSelectAccount, account);
p.setChecked(isChecked);
return p;
}
private void loadSelectAccount() {
mSelectAccount = getSelectAccount(getActivity());
}
private String getSelectAccount(final Context context) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getString(context.getString(R.string.pref_account_key), null);
}
private void setSelectAccount(final Context context, final String value) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
final Editor editor = prefs.edit();
editor.putString(context.getString(R.string.pref_account_key), value);
editor.commit();
}
}
RadioButton の機能を実装する
CheckBoxPreference そのままの機能では、複数の項目を選択できてしまう。
そこで、 RadioButton のように 1つの項目だけを選択するようにする。
private Preference buildAccountPreferences(final String account) {
final CheckBoxPreference p = new CheckBoxPreference(getActivity());
....
// 下記の1行を追加
p.setOnPreferenceChangeListener(mOnPreferenceChangeListener);
}
private final Preference.OnPreferenceChangeListener mOnPreferenceChangeListener =
new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(final Preference preference, final Object newValue) {
// true -> false ignore
if (Boolean.FALSE.equals(newValue)) {
return false;
}
// save account
final String account = String.valueOf(preference.getTitle());
setSelectAccount(getActivity(), account);
// refresh accounts preference screen
loadSelectAccount();
removeAllPreferenceScreen();
buildAccountsPreferences();
return true;
}
};
UI を CheckBox から RadioButton にする
CheckBox に RadioButton のリソースを適用する定義を作成する。
res/layout/preference_widget_checkbox.xml
<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:button="?android:attr/listChoiceIndicatorSingle"
android:clickable="false"
android:focusable="false" />
res/values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Preference" />
<style name="Preference.CheckBoxPreference">
<item name="android:widgetLayout">@layout/preference_widget_checkbox</item>
</style>
</resources>
res/values/themes.xml
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme" parent="android:Theme.Holo">
<item name="accountCheckBoxPreferenceStyle">@style/Preference.CheckBoxPreference</item>
</style>
</resources>
res/values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- PreferenceAccountFragment accountCheckBoxPreferenceStyle -->
<attr name="accountCheckBoxPreferenceStyle" format="reference" />
</resources>
AndroidManifest.xml
<activity
android:name=".PreferenceMainActivity"
android:label="@string/app_name"
android:theme="@style/Theme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
CheckBoxPreference のコンストラクタで、作成した RadioButton のリソースを指定する。
final CheckBoxPreference p = new CheckBoxPreference(getActivity(),
null, R.attr.accountCheckBoxPreferenceStyle);
完成
完成したソースファイル一式は下記のGitHubにアップした。