Set DialogFragment width and height

Robert Mirabelle
4 min readAug 29, 2019

--

Let your daily dose of Android insanity commence.

Edit 2021

This article was originally written many years ago. Thankfully, it’s now considerably easier to control the width and height of your DialogFragment. Sadly, it still must be done programmatically. But I’ve created a couple of extension methods for Kotlin that can reduce the code you need to write to this:

setWidthPercent(65)

or this:

setFullScreen()

Here are the extension methods:

Then in your DialogFragment, in onActivityCreated or later, you can simply do:

The remainder of this article is still worth a read, if for no other reason than understanding a little history and perhaps taking a little joy in my continued bashing of the Android SDK ;-)

It’s sort of mind numbing, really.

When creating a DialogFragment, you can choose to override onCreateView (which passes a ViewGroup to attach your .xml layout to) or onCreateDialog, which does not.

You mustn’t override both methods tho, because you will very likely confuse Android as to when or if your dialog’s layout was inflated! WTF?

The choice of whether to override OnCreateDialog or OnCreateView depends on how you intend to use the dialog.

  • If you will launch the dialog in a window (the normal behavior), you are expected to override OnCreateDialog.
  • If you intend to embed the dialog fragment within an existing UI layout (FAR less common), then you are expected to override OnCreateView.

Here’s yet another example of why the Android SDK the worst thing in the world.

onCreateDialog Insanity

So, you’re overriding onCreateDialog in your DialogFragment to create a customized instance of AlertDialog to display in a window. Kewl. But remember, onCreateDialog receives no ViewGroup to attach your custom .xml layout to. No problem, you simply pass null to the inflate method.

Let the madness begin.

When you override onCreateDialog, Android COMPLETELY IGNORES several attributes of the root node of the .xml Layout you inflate. This includes, but probably isn't limited to:

  • background_color
  • layout_gravity
  • layout_width
  • layout_height

This is almost comical, as you are required to set the layout_width and layout_height of EVERY .xml Layout or Android Studio will slap you with a nice little red badge of shame.

Just the word DialogFragment makes me want to puke. I could write a novel filled with Android gotchas and snafus, but this one is one of the most insidious.

To return to sanity, first, we declare a style to restore JUST the background_color and layout_gravity we expect:

<style name="MyAlertDialog" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:layout_gravity">center</item>
</style>

The style above inherits from the base theme for Dialogs (in the AppCompat theme in this example).

Next, we apply the style programmatically to put back the values Android just tossed aside and to restore the standard AlertDialog look and feel:

public class MyDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View layout = getActivity().getLayoutInflater().inflate(R.layout.my_dialog_layout, null, false);
assert layout != null;
//build the alert dialog child of this fragment
AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
//restore the background_color and layout_gravity that Android strips
b.getContext().getTheme().applyStyle(R.style.MyAlertDialog, true);
b.setView(layout);
return b.create();
}
}

The code above will make your AlertDialog look like an AlertDialog again. Maybe this is good enough.

But wait, there’s more!

If you’re looking to set a SPECIFIC layout_width or layout_height for your AlertDialog when it's shown (very likely), then guess what, you ain't done yet!

The hilarity continues as you realize that if you attempt to set a specific layout_width or layout_height in your fancy new style, Android will completely ignore that, too!:

<style name="MyAlertDialog" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:layout_gravity">center</item>
<!-- NOPE!!!!! --->
<item name="android:layout_width">200dp</item>
<!-- NOPE!!!!! --->
<item name="android:layout_height">200dp</item>
</style>

To set a SPECIFIC window width or height, you get to head on over to a whole ‘nuther method and deal with LayoutParams:

@Override
public void onResume() {
super.onResume();
Window window = getDialog().getWindow();
if(window == null) return;
WindowManager.LayoutParams params = window.getAttributes();
params.width = 400;
params.height = 400;
window.setAttributes(params);
}

Many folks follow Android’s bad example of casting WindowManager.LayoutParams up to the more general ViewGroup.LayoutParams, only to turn right around and cast ViewGroup.LayoutParamsback down to WindowManager.LayoutParams a few lines later. Effective Java be damned, that unnecessary casting offers NOTHING other than making the code even harder to decipher.

Side note: There are some TWENTY repetitions of LayoutParams across the Android SDK - a perfect example of radically poor design.

In Summary

For DialogFragments that override onCreateDialog:

  • To restore the standard AlertDialog look and feel, create a style that sets background_color = transparent and layout_gravity = center and apply that style in onCreateDialog.
  • To set a specific layout_width and/or layout_height, do it programmatically in onResume with LayoutParams
  • To maintain sanity, try not to think about the Android SDK.

--

--