うさがにっき

読書感想文とプログラムのこと書いてきます

AndroidのPreferenceを使う

概要

AndroidのPreferenceActivityを使い、設定の機能を使ってみる
単純なxmlファイルを編集するだけで設定画面が完成する

詳細

まずはres/xml

<?xml version="1.0" encoding="utf-8"?>

<!-- keyを使って設定オブジェクトを取得する -->
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:key="pref_first_preferencescreen_key"
    android:title="Preferences">

    <!-- Categoryでわけることができる -->
    <PreferenceCategory
        android:title="User">

        <EditTextPreference
            android:key="pref_username"
            android:summary="Username:"
            android:title="Username"/>

    </PreferenceCategory>

    <PreferenceCategory
        android:title="Application">

        <!-- intentを起動するものについてはPreferenceを使う -->
        <Preference
            android:key="pref_rate"
            android:summary="Rate the app in the store!"
            android:title="Rate the app"/>

        <Preference
            android:key="pref_share"
            android:summary="Share the app with your friends"
            android:title="Share it"/>

        <com.manning.androidhacks.hack004.preference.EmailDialog
            android:dialogIcon="@drawable/ic_launcher"
            android:dialogTitle="Send Feedback"
            android:dialogMessage="Do you want to send an email with feedback?"
            android:key="pref_sendemail_key"
            android:negativeButtonText="Cancel"
            android:positiveButtonText="OK"
            android:summary="Send your feedback by e-mail"
            android:title="Send Feedback"/>

        <com.manning.androidhacks.hack004.preference.AboutDialog
            android:dialogIcon="@drawable/ic_launcher"
            android:dialogTitle="About"
            android:key="pref_about_key"
            android:negativeButtonText="@null"
            android:title="About"/>

    </PreferenceCategory>

</PreferenceScreen>

このxmlがUIも作成してくれる、のでlayoutは必要なし。

ロジック
PreferenceActivityを継承する

public class MainActivity extends PreferenceActivity implements
    OnSharedPreferenceChangeListener {

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // setContentView()の代わりに上で作成したxmlを引数としたaddPreferencesFromResourceを呼ぶ
    addPreferencesFromResource(R.xml.prefs);

    // Intent発行が必要がPreferenceに大してIntentを付与する、ここはShare
    Preference sharePref = findPreference("pref_share");
    Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.setType("text/plain");
    shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Check this app!");
    shareIntent.putExtra(Intent.EXTRA_TEXT,
        "Check this awesome app at: ...");
    sharePref.setIntent(shareIntent);

	// Intent発行が必要がPreferenceに大してIntentを付与する、ここはmarket
    Preference ratePref = findPreference("pref_rate");
    Uri uri = Uri.parse("market://details?id=" + getPackageName());
    Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
    ratePref.setIntent(goToMarket);

    updateUserText();
  }

  @Override
  protected void onResume() {
    super.onResume();

    getPreferenceScreen().getSharedPreferences()
        .registerOnSharedPreferenceChangeListener(this);

  }

  @Override
  protected void onPause() {
    super.onPause();

    getPreferenceScreen().getSharedPreferences()
        .unregisterOnSharedPreferenceChangeListener(this);
  }

  // preferenceの値が変更されるとcallされる 
  @Override
  public void onSharedPreferenceChanged(
      SharedPreferences sharedPreferences, String key) {

    // user名に変更があった場合は、Textをupdateする
    if (key.equals("pref_username")) {
      updateUserText();
    }
  }

  private void updateUserText() {
    EditTextPreference pref;
    pref = (EditTextPreference) findPreference("pref_username");
    String user = pref.getText();

    if (user == null) {
      user = "?";
    }

    pref.setSummary(String.format("Username: %s", user));
  }
}

独自部品を使う場合には以下のようにする。
独自部品を使う場合にもPreferenceのウィジェットを継承する、ダイアログの場合はDialogPreference

public class EmailDialog extends DialogPreference {
  Context mContext;

  // コンストラクタは通常のカスタムViewと同じ
  public EmailDialog(Context context) {
    this(context, null);
  }

  public EmailDialog(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public EmailDialog(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    mContext = context;
  }

  @Override
  public void onClick(DialogInterface dialog, int which) {
    super.onClick(dialog, which);

    // このやり方だとPOSITIVE,NEGATIVEでしかとれないっぽい
    if (DialogInterface.BUTTON_POSITIVE == which) {
      // emailのインテント作成
      LaunchEmailUtil.launchEmailToIntent(mContext);
    }
  }
}

一応、ダイアログのレイアウトを作成するやり方もある
DialogPreference内でonCreateDialogViewを継承し、表示したいlayoutを返す

  @Override
  protected View onCreateDialogView() {
    LinearLayout layout = new LinearLayout(mContext);
    layout.setOrientation(LinearLayout.VERTICAL);
    TextView splashText = new TextView(mContext);
    String fmt = "Version %s<br />"
        + "<a href=\"http://manning.com/sessa\">MoreInfo</a>";
    try {
      String pkg = mContext.getPackageName();
      mVersionNumber = mContext.getPackageManager().getPackageInfo(pkg,
          0).versionName;
    } catch (NameNotFoundException e) {
      e.printStackTrace();
    }

    if (mVersionNumber != null) {
      String aboutMsg = String.format(fmt, mVersionNumber);
      splashText.setText(Html.fromHtml(aboutMsg));
      splashText.setMovementMethod(LinkMovementMethod.getInstance());
    }

    layout.addView(splashText);

    return layout;
  }

感想

ちょっと作り方が特殊すぎて使いづらい感じ
後、レイアウトに手を入れるのが難しそうなので、本当に簡単な設定画面を作るときぐらいしか使わなそう