DialogFragment には表示するダイアログのインスタンスを自分で作成するための onCreateDialog() というメソッドが用意されています。
このメソッドを Override して、任意の Dialog クラスのインスタンスを返すことでオリジナルのテーマを適用したダイアログを表示することができます。
- public class MyDialogFragment extends DialogFragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- // ダイアログの中に表示する View を返す
- ...
- }
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- Dialog dialog = new Dialog(getActivity(), R.style.MyDialogTheme);
- return dialog;
- }
- }
- <style name="MyDialogTheme" parent="@android:style/Theme.Holo.Light.Dialog">
- <item name="android:windowActionBar">false</item>
- <item name="android:windowNoTitle">true</item>
- </style>
ダイアログのサイズを指定する方法で、この MyDialogFragment の大きさを指定しようとした場合、
- public class MyDialogFragment extends DialogFragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- // ダイアログの中に表示する View を返す
- ...
- }
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- Dialog dialog = new Dialog(getActivity(), R.style.MyDialogTheme);
- WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
- DisplayMetrics metrics = getResources().getDisplayMetrics();
- int dialogWidth = (int) (metrics.widthPixels * 0.8);
- int dialogHeight = (int) (metrics.heightPixels * 0.8);
- lp.width = dialogWidth;
- lp.height = dialogHeight;
- dialog.getWindow().setAttributes(lp);
- return dialog;
- }
- }
DialogFragment の実装をみると getLayoutInflater() でフィールドの mDialog に onCreateDialog() の戻り値を格納しています。
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/app/DialogFragment.java#391
- 391 /** @hide */
- 392 @Override
- 393 public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
- 394 if (!mShowsDialog) {
- 395 return super.getLayoutInflater(savedInstanceState);
- 396 }
- 397
- 398 mDialog = onCreateDialog(savedInstanceState);
- ...
- 415 }
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/app/FragmentManager.java#795
- 795 f.mView = f.onCreateView(f.getLayoutInflater(f.mSavedFragmentState),
- 796 container, f.mSavedFragmentState);
この後に DialogFragment の onActivityCreated() が呼ばれ、ここで onCreateView() で返した View がダイアログに setContentView() でセットされます。
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/app/DialogFragment.java#456
- 456 @Override
- 457 public void onActivityCreated(Bundle savedInstanceState) {
- 458 super.onActivityCreated(savedInstanceState);
- 459
- 460 if (!mShowsDialog) {
- 461 return;
- 462 }
- 463
- 464 View view = getView();
- 465 if (view != null) {
- 466 if (view.getParent() != null) {
- 467 throw new IllegalStateException("DialogFragment can not be attached to a container view");
- 468 }
- 469 mDialog.setContentView(view);
- 470 }
- 483 }
- 1106 public View getView() {
- 1107 return mView;
- 1108 }
getLayoutInflater()
→ onCreateDialog()
↓
onCreateView()
↓
onActivityCreated()
のような順番になります。onCreateDialog() が一番最初です。
onActivityCreated() で Dialog の setContentView() が呼ばれるわけですが、Dialog の setContentView() は Window の setContentView() を呼び出しているだけです。
- 84 Window mWindow;
- 146 Dialog(Context context, int theme, boolean createContextWrapper) {
- 155 mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- 156 Window w = PolicyManager.makeNewWindow(mContext);
- 157 mWindow = w;
- 163 }
- 466 public void setContentView(View view) {
- 467 mWindow.setContentView(view);
- 468 }
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/view/Window.java#922
- 922 public abstract void setContentView(View view);
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java#264
- 258 @Override
- 259 public void setContentView(View view) {
- 260 setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
- 261 }
- 262
- 263 @Override
- 264 public void setContentView(View view, ViewGroup.LayoutParams params) {
- 265 if (mContentParent == null) {
- 266 installDecor();
- 267 } else {
- 268 mContentParent.removeAllViews();
- 269 }
- 270 mContentParent.addView(view, params);
- 271 final Callback cb = getCallback();
- 272 if (cb != null && !isDestroyed()) {
- 273 cb.onContentChanged();
- 274 }
- 275 }
- 2738 private void installDecor() {
- 2739 if (mDecor == null) {
- 2740 mDecor = generateDecor();
- 2741 mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
- 2742 mDecor.setIsRootNamespace(true);
- 2743 }
- 2744 if (mContentParent == null) {
- 2745 mContentParent = generateLayout(mDecor);
- 2746
- 2498 protected ViewGroup generateLayout(DecorView decor) {
- 2499 // Apply data from current theme.
- 2500
- 2501 TypedArray a = getWindowStyle();
- 2502
- 2503 if (false) {
- 2504 System.out.println("From style:");
- 2505 String s = "Attrs:";
- 2506 for (int i = 0; i < com.android.internal.R.styleable.Window.length; i++) {
- 2507 s = s + " " + Integer.toHexString(com.android.internal.R.styleable.Window[i]) + "="
- 2508 + a.getString(i);
- 2509 }
- 2510 System.out.println(s);
- 2511 }
- 2512
- 2513 mIsFloating = a.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false);
- 2514 int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
- 2515 & (~getForcedWindowFlags());
- 2516 if (mIsFloating) {
- 2517 setLayout(WRAP_CONTENT, WRAP_CONTENT);
- 2518 setFlags(0, flagsToUpdate);
- 2519 } else {
- 2520 setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
- 2521 }
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/view/Window.java#604
- 604 public void setLayout(int width, int height) {
- 605 final WindowManager.LayoutParams attrs = getAttributes();
- 606 attrs.width = width;
- 607 attrs.height = height;
- 608 if (mCallback != null) {
- 609 mCallback.onWindowAttributesChanged(attrs);
- 610 }
- 611 }
ということで、意図通りにするには
- public class MyDialogFragment extends DialogFragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- // ダイアログの中に表示する View を返す
- ...
- }
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- Dialog dialog = getDialog();
- WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
- DisplayMetrics metrics = getResources().getDisplayMetrics();
- int dialogWidth = (int) (metrics.widthPixels * 0.8);
- int dialogHeight = (int) (metrics.heightPixels * 0.8);
- lp.width = dialogWidth;
- lp.height = dialogHeight;
- dialog.getWindow().setAttributes(lp);
- }
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- Dialog dialog = new Dialog(getActivity(), R.style.MyDialogTheme);
- return dialog;
- }