Androidで動く携帯Javaアプリ作成入門
連載インデックスへ
Androidで動く携帯Javaアプリ作成入門(19)

XMLレイアウトでAndroidアプリに“設定画面”を追加


株式会社イーフロー
緒方聡
2010/8/19

リスナーの登録

 XMLですべてのレイアウトを定義できますが、「値が変更された」「クリックされた」というリスナーは、コーディングしなければなりません。以下に1つ取り上げてみます。

// チェックボックス設定のインスタンスを、キーを基に取得する
CheckBoxPreference cbp = (CheckBoxPreference)findPreference("checkbox_preference");
// リスナーを設定する
cbp.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        String summary;
        if (((Boolean)newValue).booleanValue()) {
            summary = "Selected";
        } else {
            summary = "Unselected";
        }
        // 更新された値に応じて概要を変更する
        ((CheckBoxPreference)preference).setSummary(summary);
        // 変更を適用するために true を返す
        return true;
    }
});

 設定を変更することで、以下のように概要が変化します。

図3 概要の変化
図3 概要の変化
- PR -

 XMLレイアウトで必要なコーディングは、基本的にこのリスナー登録だけです。今回のリスナーは「入力の状態に応じて概要を変更する」のみですが、実際には「入力チェックを行って、不正な入力の際には値を反映させない(falseを返す)」「リングトーン設定であれば、実際にデバイスの設定を変更する」などが行われます。

 実際に動作させてみて気が付かれた方がいるかもしれませんが、リスナーは変更時に概要を設定し直すので、画面表示時には状態が分かりません。

図4 開いてみるまで設定内容が分からない
図4 開いてみるまで設定内容が分からない

 このような場合はPreferenceManagerを使用して、現在の設定内容を取得します。PreferenceManagerの使い方は、この後すぐに解説します。

設定値を取得する

 PreferenceActivityで設定された内容は、PreferenceActivityの表示時に自動的に読み込まれますが、設定された内容をアプリ本体で取得する場合は、PreferenceManagerとSharedPreferencesを使用します。

// 【1】デフォルトの SharedPreference を取得する
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
// 【2】設定内容をコミットする
sp.edit().commit();
// 【3】設定内容をすべて取得する
Map<String, ?> map = sp.getAll();

CharSequence[] list = new CharSequence[map.size()];
int i = 0;
for (String key : map.keySet()) {
list[i++] = key + "=" + map.get(key);
}

 【1】では、デフォルトのSharedPreferencesを取得しています。SharedPreferencesは、名前を付けて取得するメソッド「ContextWrapper#getSharedPreferences(String, int)」が用意されていて、このメソッドを使用する場合、以下の呼び出しが同じ動作になります。

getSharedPreferences("com.example.android.preference_preferences", MODE_PRIVATE);

 デフォルトのSharedPreferencesの名前は、「パッケージ名_preference」というふうに決まっています。設定を初期化したい場合は、このファイルを削除すれば簡単に実現できます。1つのアプリで複数の設定を使用したい場合は、デフォルトを使用するのではなく、上記メソッドを使用して作成するとよいでしょう。作成する際に、第2引数に、定数「MODE_WORLD_READABLE」「MODE_WORLD_WRITEABLE」を指定してパーミッションをコントロールできます。

 【2】では、SharedPreferencesのエディタを取得して、設定内容をコミットしています。SharedPreferencesは、永続化のためにストレージ上にファイルとして保存されますが、保存されるのはアプリが終了するタイミングで、それまではメモリ上に展開されています。ここでcommit()メソッドを呼び出しておくことで、メモリ上で変更された内容をストレージにコミットし、その内容を取得するようにしています。

 【3】では、すべての設定項目をMapオブジェクトとして取得しています。個別にキーとデフォルト値を指定して値を取得するgetBoolean()、getFloat()、getInt()、getLong()、getString()が用意されているので、通常はこちらを使用します。

コンポーネントの依存関係を決めるには

 しばしば設定項目には依存関係があるものもあります。例えばWi-Fiを使う場合はアクセスポイントの設定が必要ですが、Wi-Fiを使用しない場合はアクセスポイントの設定は不要です。

 今回のアプリでは、以下のように動作します。

図5 親がチェックされている場合のみ、子が編集可能
図5 親がチェックされている場合のみ、子が編集可能

 このような依存関係もXMLで簡単に定義できます。

【1】↓依存元の設定項目を定義
<CheckBoxPreference
android:key="parent_checkbox_preference"
android:title="@string/parent_preference_title"
android:summary="@string/parent_preference_summary" />
<CheckBoxPreference
android:key="child_checkbox_preference"
【2】↓依存元のキーを指定
android:dependency="parent_checkbox_preference"
【3】↓自動的に使用可・使用不可が切り替わるレイアウトを設定
android:layout="?android:attr/preferenceLayoutChild"
android:title="@string/child_preference_title"
android:summary="@string/child_preference_summary" />

 親の設定項目を定義し、子の設定項目のandroid:dependencyに親のキーを、「android:layout」に「?android:attr/preferenceLayoutChild」を指定します。この設定を行うことで、「親がチェックされているときだけ子が使用できる」という動作が実現できます。

 これをコーディングで行う場合、以下のようになります。

// 子設定を生成する際にonDependencyChangedをオーバーライド
CheckBoxPreference childCheckBoxPref = new CheckBoxPreference(this) {
    @Override
    public void onDependencyChanged(Preference dependency, boolean disableDependent) {
        setEnabled(!disableDependent);
    }
};
 
setPreferenceScreen(createPreferenceHierarchy());
// setPreferenceScreen が終わってから setDependency() を呼び出し
getPreferenceManager().findPreference("child_checkbox_preference").setDependency("parent_checkbox_preference");

 本来であれば、setDependency()というメソッドで依存関係を設定できますが、setLayoutResourceで設定するandroid.R.attr.preferenceLayoutChildが正常に機能しないため、期待通りの動作になりません(常に使用可能です)。ApiDemoのオリジナルのソースコードは別の不具合(setKey()が行われていない)がありますが、不具合を修正してもやはり期待通りに動作しません。

 Androidのソースコードを検索してsetDependency()を使用している個所を確認したところ、使用しているすべてでXMLレイアウトの補助として使用されていることが分かり、XMLレイアウトで定義したファイルに対してsetDependency()を行ったところ、期待通りの動作になるため、これはもしかするとAndroidの不具合なのかもしれません。

 上記の回避方法でも、まったく同様の動作ですが、XMLレイアウトは属性を2つ追加するだけなので、前述したとおりレイアウトはXMLで行うことを強く推奨します。

次回は、アニメーションで華やかな演出を

 アプリに設定を持たせたい場合は、ごく簡単なものであればMenuなどでトグル状態を実装するなどの方法がありますが、いずれにせよ設定された値は永続化しなければならないため、その手間を考えるとPreferenceActivityを使うことは良い選択肢といえるでしょう。

 次回はアニメーションで華やかな演出を行う方法について解説する予定です。

@IT関連記事


グーグルは、○○おもいっきり、テレビ
安藤幸央のランダウン(52)
 5月に米国で開催された、開発者向けカンファレンス「Google I/O 2010」の模様を、Google TVやApp Engine、Androidを中心にレポートする
Java Solution」フォーラム 2010/6/16
Titaniumで始めるモバイルアプリ作成の基礎知識
Web技術でネイティブアプリを作れるTitanium(2) 
ついに出た1.0版について、その特徴と使い方、開発の勘所を解説します。今後もiPhone開発に使え得るのか注目です
Androidアプリはビジネスになるのか
ものになるモノ、ならないモノ(38)
 「iPhoneアプリの次はAndroid?!」NECビッグローブのAndroidアプリ販売サイト「andronavi」を通して、その可能性に迫る
Master of IP Network」フォーラム 2010/2/12
Androidはオタクとオシャレのハイブリッドで流行る!
日本Androidの会 女子部に聞く 「女子部」の成り立ちや活動内容を中心に、Androidマーケットの問題点、UIデザインの重要性、ライバルであるiPhoneについて、など
今日から始める! Androidケータイアプリ作成の基礎
デザイナも知っておきたい「Androidアプリ」とは 日に日に国内でのニュースが増えているAndroidケータイ。その特徴を押さえてアプリ作成を始めるための基礎を紹介します
Androidアプリで高速描画チューニングをするコツ
インタビュー特集:Google直伝!(1) Googleのさまざまなサービスを使いこなすコツをグーグル担当者に聞くインタビュー。初回は日本で端末販売がせまるAndroidについて
リッチクライアント & 帳票」フ ォーラム 2009/4/21

ケータイ分野以外の組み込みデバイス開発の現場でも注目を集めている「Android」。組み込みデバイスへの適用からアプリケーション開発、イベントレポート、ニュースなどAndroidに関するさまざまな技術情報・最新動向をお届けします!

1-2-3

 Index
第19回 XMLレイアウトでAndroidアプリに“設定画面”を追加
  Page1
AndroidはJavaの著作権を侵害? 今後はどうなる?
Androidアプリに設定画面を追加するのは簡単だ
Activityの派生クラス「PreferenceActivity」とは
  Page2
設定画面で使用可能な6つのコンポーネント
XMLレイアウトによる設定画面の構築
コラム 「画面をXMLで定義する意味」
Page3
コンポーネントの依存関係を決めるには
次回は、アニメーションで華やかな演出を

Androidで動く携帯Javaアプリ作成入門 バックナンバー 連載インデックスへ»


ご意見、ご感想は Smart&Social 会議室へどうぞ


 Smart&Social フォーラム トップページへ


TechTargetジャパン

Smart & Social フォーラム 新着記事

@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

RSSフィード

キャリアアップ

@IT Sepcial

イベントカレンダー

PickUpイベント

- PR -
もっと見る
- PR -

お勧め求人情報

ホワイトペーパーTechTargetジャパン

@IT Sepcial
ソリューションFLASH