執筆中
DialogFragmentを利用するときのチェックポイント
Activityにレイアウトを準備せずに使えるDialogFragmentは使いやすい。
ただ最初は少し癖があるので、要点をおさらいしておくとよい。
そんなTopicをご提供。
参考にするリンク
- 名前
- URL
基本的な作り方
まずは基本的な作り方から。
1度見ておけばそうそう間違わないことから、ついやってしまうことまで挙げていく。
publicなクラスで作成する
DialogFragmentは必ず public なクラスでなければならない。
なぜなら configChanges や onRestart が起こる際に再描画で呼ばれるので、
ActivityManager(の呼び先)がインスタンスの生成を行える必要があるからである。
まぁ、Activity を「class MyActivity extends Activity」で作るのと同じことだ。
実際に呼び出しが掛かるのは android.app あたりのパッケージなので、
どうしても見えないとインスタンス生成できないってことになる。
ありがちなのは「private static final class」にしてしまうことだな!
私もよくやってしまう。慣れるとそうでもないんだが。
リソースや表示のテストの観点も考えると、いっそのことDialogFragmentは同じパッケージに置けばいい。
com.test.main.MyActivity.java
com.test.dialog.MyDialogFragment.java
的な。
デフォルトコンストラクタを作っておく
初回起動データを渡すためにコンストラクタに引数を入れるのはいいが、必ずデフォルトコンストラクタを作っておくこと。
でないとConfigurationChangedが起きたあとにエラーが発生する。
こんな風にしていると・・・
public class TestDialog extends DialogFragment {
int messageId;
public TestDialog(int resId) {
messageId = resId;
}
縦横切り替えしたらこんなエラーがでる。
make sure class name exists, is public, and has an empty constructor that is public
デフォルトコンストラクタ無いと画面復帰できないんだけど?って感じ。
後述する public static final void show(FragmentManager manager) を作っておけば、
そちらで Fragment#setArguments() ができるのでデータ受け渡しの心配もない。
public class TestDialog extends DialogFragment {
public static final void show(FragmentManager manager, int resId) {
L.std();
TestDialog dialog = new TestDialog();
Bundle args = new Bundle();
args.putInt("RESID", resId);
dialog.setArguments(args);
dialog.show(manager, TestDialog.class.getSimpleName());
}
~~~
メンドウなときは以下のようにしてしまうがな!
public class TestDialog extends DialogFragment {
int messageRes;
public static final void show(FragmentManager manager, int resId) {
L.std();
TestDialog dialog = new TestDialog();
dialog.messageRes = resId;
dialog.show(manager, TestDialog.class.getSimpleName());
}
~~~
public static final void show(FragmentManager manager)を提供する
これは必須ではない。
しかし、複数の画面にDialogを提供する可能性が高いDialogFragmentである。
手続きを1箇所にすることで簡素化を図るとともに、
データの受け渡しを制限することでカプセル化を行っておきたい。
また必要に応じて hide(or close), update を提供するのもよいと思う。
public class TestDialog extends DialogFragment {
private static final String TAG
= TestDialog.
class.
getSimpleName();
public static final void show(FragmentManager manager) {
L.std();
TestDialog dialog = new TestDialog();
dialog.show(manager, TAG);
}
public static final void update(FragmentManager manager) {
// 更新処理は必ずここを通るので、処理が散見しなくていいね。
Fragment temp = manager.findFragmentByTag(TAG);
// このチェックはシステム上不要なら null チェックで十分。
// 今回は掲載用に instanceof なんて使ってます。
if (temp instanceof TestDialog) {
TestDialog dialog = (TestDialog) temp;
// タイトル変更、ChoicePosition調整、リストデータ更新、etc...
dialog.getDialog().setTitle("変更!");
}
}
public static final void hide(FragmentManager manager) {
Fragment temp = manager.findFragmentByTag(TAG);
if (temp instanceof TestDialog) {
TestDialog dialog = (TestDialog) temp;
dialog.dismiss();
}
}
~~~
表示スタイル
DialogFragment#setStyle() は表示するダイアログの見た目を変える。
注意して欲しいのは、Dialogの画面生成が行われる onCreateDialog() までの間に行う必要があること。
onCreateView()では遅すぎるので注意しよう。
オススメは DialogFragment の new 時点で入れてしまうこと。
データを覚えるために setArguments() を行うついでに入れてしまおう。
第一引数はDialogの表示項目+αの設定で、
- STYLE_NORMAL
- いつものダイアログ画面
- STYLE_NO_TITLE
- タイトルが表示されない。
- STYLE_NO_FRAME
- タイトルが表示されないどころか、設定したViewの大きさで形が自由自在。
- STYLE_NO_INPUT
- 見た目はSTYLE_NO_FRAMEで、キー入力などのイベントが一切来ない。
といった感じ。
特に STYLE_NO_FRAME は優秀で、onCreateView()で返したViewが適用されるので非常に広い領域が使える。
ViewGroupのツリーは
- DecorView
- FrameLayout
- FrameLayout(android.R.id.content)
- onCreateView()で返したView
- ViewStub(android.R.id.action_mode_bar_stub)
となるので、作るときは <merge> を使いたくなるが、
onCreateView() の ViewGroup container が null だと落ちることになる。
ので素直にRelativeLayoutとか使おう。
onCreateDialog()とonCreateView()の違い
onCreateDialog()の実装例
onCreateView()の実装例
少し拡張する
コンテキストメニューを出す
オプションメニューを出す
DialogFragmentのオプションメニューを出すには、Dialog側のMenu関連メソッドをオーバーライドする必要がある。
特殊な使い方
レイアウトにFragmentを入れる場合の注意
PreferenceFragmentを表示する
ListFragmentを表示する
まとめ
関連リンク
取得中です。
最終更新:2012年11月17日 00:13