PreferenceActivityの利用

PreferenceActivityを共円チェッカーで利用しました。
その中でCheckBoxPreference、EditTextPreferenceを利用したので備忘録でも。


まず、resフォルダ内にxmlフォルダを作成。
その中にsetting.xml(ファイル名は自由なはず)を作成。

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:title="Preferences"
        >
        <CheckBoxPreference
            android:key="auto_send"
            android:title="自動送信"
            android:summary="自動で送信します。"
            />
        <EditTextPreference
            android:key="name"
            android:title="名前"
            android:dialogTitle="名前を入力してください。"
            android:maxLength="20"
            android:inputType="text"
            />
    </PreferenceCategory>
</PreferenceScreen>

実際には、android:titleなどは、valuesフォルダにstrings.xmlを作っています。
そこは、サンプルなのでテキトーです。
EditTextPreferenceには20文字の入力制限のために「android:maxLength="20"」を設定しています。
また、改行を不可としたかったため、「android:inputType="text"」も設定してあります。


そして、SamplePreferenceActivity.javaです。

package hm.orz.chaos114.android.sample;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.widget.Toast;

public class SamplePreferenceActivity extends PreferenceActivity {

    /** キー:自動送信 */
    public static final String KEY_AUTO_SEND = "auto_send";

    /** キー:名前 */
    public static final String KEY_NAME = "name";

    /** デフォルト値:名前 */
    public static final String DEFAULT_NAME = "no name";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.setting);

        init();
    }

    private void init() {
        // 自動送信チェックボックスの設定
        CheckBoxPreference autoSendCheckBox = (CheckBoxPreference) findPreference(KEY_AUTO_SEND);
        autoSendCheckBox
                .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                    @Override
                    public boolean onPreferenceChange(Preference preference,
                            Object newValue) {
                        boolean checked = (Boolean) newValue;
                        if (checked) {
                            // チェック時
                            Toast.makeText(
                                    SamplePreferenceActivity.this,
                                    "\""
                                            + getName(SamplePreferenceActivity.this)
                                            + "\"として自動送信します。",
                                    Toast.LENGTH_SHORT).show();
                        }
                        return true;
                    }
                });

        // 名前入力領域の設定
        EditTextPreference nameText = (EditTextPreference) findPreference(KEY_NAME);
        nameText
                .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                    @Override
                    public boolean onPreferenceChange(Preference preference,
                            Object newValue) {
                        String value = newValue.toString();
                        // 設定された名称を設定する
                        preference.setSummary("name : " + value);
                        return true;
                    }
                });
        nameText.setSummary("name : "
                + getName(SamplePreferenceActivity.this));
    }

    /**
     * 自動送信を取得します。
     * 
     * @param context アプリケーション情報
     * @return 自動送信
     */
    public static boolean isAutoSend(Context context) {
        SharedPreferences sharedPreferences = PreferenceManager
                .getDefaultSharedPreferences(context);
        boolean autoSend = sharedPreferences.getBoolean(KEY_AUTO_SEND, false);
        return autoSend;
    }

    /**
     * 名前を取得します。
     * 
     * @param context アプリケーション情報
     * @return 設定されている名前(未設定の場合は{@link #DEFAULT_NAME}
     */
    public static String getName(Context context) {
        SharedPreferences sharedPreferences = PreferenceManager
                .getDefaultSharedPreferences(context);
        String name = sharedPreferences.getString(KEY_NAME,
                DEFAULT_NAME);
        return name;
    }

    /**
     * 名前を設定します。
     * 
     * @param context アプリケーション情報
     * @return 設定されている名前(未設定の場合は{@link #DEFAULT_NAME}
     */
    public static void setName(Context context, String name) {
        SharedPreferences sharedPreferences = PreferenceManager
                .getDefaultSharedPreferences(context);
        Editor editor = sharedPreferences.edit();
        editor.putString(KEY_NAME, name);
        editor.commit();
    }
}


onCreateメソッドにて、いろいろ設定しておきます。
setOnPreferenceChangeListenerで、値が変更された場合の処理を記述しておきます。
CheckBoxPreferenceについては、チェックボックスがチェックされたときにToastを表示したかったので、このようになっています。
onPreferenceChangeメソッドのnewValueはBoolean型にcastしています。
チェックされた場合はtrue、チェックが外された場合はfalseとなります。
そして、返却値はJavaDocにあるように、変更をPreferenceに反映したい(描画を変更したい)場合はtureを返すことになります。
(何らかのエラーチェックなどで反映したくない場合はfalseを返す?)

また、EditTextPreferenceでは、設定された名称をSummaryに表示したかったため、onPreferenceChangeの引数であるPreferenceに、setSummaryで新しい値を設定しています。
(EditTextPreferenceにて、Preference#callChangeListenerにStringオブジェクトを渡しているため、newValueはStringにcastするべきかもしれません)
初期値を変更するために、initメソッド内からもsetSummaryを呼び出しています。
("name : "の部分は定数化するか、この設定処理自体をメソッド化するべきかもしれません)


そして、Preferencesに対しての操作メソッドをこのクラスに定義しています。
staticメソッドとすることで、Contextを持っているクラス(Activityなど)からは、このクラスをインスタンス化せずに各値にアクセスすることができます。
(contextの持つ、package名が同じでさえあればよい?)


(Preferencesのキーをpublicな定数として持っていますが、上記のpublic staticなメソッドを持っているので、privateでもよかったかな?)


あと、Activityの追加となるので、AndroidManifest.xmlに追加も必要となります。

<activity android:name=".SamplePreferenceActivity"
    android:label="@string/app_name">
</activity>


と、いうことで、Preferencesを初めて利用してみました。
結構簡単に設定画面が作れるのは便利です。
ただ、EditTextをそのまま表示して入力できるようにするなど、変わったことをしようとすると、もう少し勉強しないといけないかと思います。