225

Let's say I specify the layout of my DialogFragment in an xml layout file named my_dialog_fragment.xml and I specify the layout_width and layout_height values of its root view to a fixed value (e.g. 100dp). I then inflate this layout in my DialogFragment's onCreateView(...) method as follows:

View view = inflater.inflate(R.layout.my_dialog_fragment, container, false);

When my DialogFragment appears, it does not respect the layout_width and layout_height values specified in its xml layout file and instead shrinks or expands depending on its content. Does anybody know whether or how I can get my DialogFragment to respect the layout_width and layout_height values specified in its xml layout file? At the moment I'm having to specify the width and height of the Dialog again in my DialogFragment's onResume() method as follows:

getDialog().getWindow().setLayout(width, height);

The problem with this is that I have to remember to make any future changes to the width and height in two places.

Adil Hussain
  • 30,049
  • 21
  • 112
  • 147

30 Answers30

199

If you convert directly from resources values:

int width = getResources().getDimensionPixelSize(R.dimen.popup_width);
int height = getResources().getDimensionPixelSize(R.dimen.popup_height);        
getDialog().getWindow().setLayout(width, height);

Then specify match_parent in your layout for the dialog:

android:layout_width="match_parent"
android:layout_height="match_parent"

Now you only have to worry about one place (i.e. your DialogFragment.onResume method). It's not perfect but at least it works for having a RelativeLayout as the root of your dialog's layout file.

Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
Blix247
  • 2,022
  • 1
  • 12
  • 2
  • 3
    This answer doesn't work in my case (for DialogFragment). I had to use FragmentLayout params for change size of showing window. – Rusfearuth Dec 26 '12 at 00:41
  • 3
    I have had to wrap my layout into `RelativeLayout` and it helped me. Many thanks for the solution - it saved me a lot of time. – Johnny Doe Jul 23 '13 at 12:06
  • 69
    This works great for me (Android 4.0+), once I realised this must be in **`onResume()`**, not `onCreateView()`. (My root layout is RelativeLayout wrapped in a ScrollView.) – Jonik Feb 26 '14 at 14:54
  • 19
    Useful in some cases: use the whole screen width: `int width = getResources().getDisplayMetrics().widthPixels` – Jonik Feb 27 '14 at 12:18
  • you can also call this from inside `DialogFragment.onCreateDialog()` – Richard Le Mesurier Sep 01 '14 at 14:57
  • 7
    +1 for Jonik. -1 for Richard. I always use support fragments and have never been able to get this to work in `onCreateDialog()`. Needs to be in `onResume()`. – MinceMan Sep 05 '14 at 14:57
  • This does work, but there are padding & margin in the customView's parent views. If I put customView's expected width and height in `getDialog().getWindow().setLayout(width, height)`, the customView will result in a smaller size. To fix this, I have to traverse parent views of customView and clear their padding & margin. – Weekend Oct 22 '15 at 06:29
  • What if I want the height to be `WRAP_CONTENT` but width a specified dimension? How to pass `WRAP_CONTENT` to height in this way? – DYS Jul 14 '16 at 06:10
  • +1 for Jonic. Finally, after one long day of searching but not finding the solution. I am super-not-impressed by the image manipulation features of DialogFragment, in particular because images are stretched per default. Who ever wants that default? Nobody. – carl Jul 30 '16 at 14:42
  • @Weekend i am facing the same issue as you i want to know how you solved it. if i set layout(anywidth, 568); the height is smaller than 568 and hence my view scrolls i want the exact height to be set in the function. What are the values of padding and margin for the default dialog android – Aman Verma Nov 18 '17 at 20:43
  • getDialog().getWindow().setLayout(WRAP_CONTENT, WRAP_CONTENT) will work. We can also pass -1(or MATCH_PARENT) and -2(or WRAP_CONTENT) – JEGADEESAN S Jan 06 '18 at 09:20
181

I ended up overriding Fragment.onResume() and grabbing the attributes from the underlying dialog, then setting width/height params there. I set the outermost layout height/width to match_parent. Note that this code seems to respect the margins I defined in the xml layout as well.

@Override
public void onResume() {
    super.onResume();
    ViewGroup.LayoutParams params = getDialog().getWindow().getAttributes();
    params.width = LayoutParams.MATCH_PARENT;
    params.height = LayoutParams.MATCH_PARENT;
    getDialog().getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
}
Sergii
  • 1,521
  • 3
  • 24
  • 37
jmaculate
  • 2,976
  • 2
  • 17
  • 14
  • 1
    @jmaculate - Quick question: when you are casting to `(android.view.WindowManager.LayoutParams)`, what are you casting it from? I was puzzled when choosing the correct import for `LayoutParams` appearing in the first 3 lines of the function. Ended up choosing `(android.view.WindowManager.LayoutParams)`. Is this supposed to be correct? – Dev-iL Dec 13 '14 at 12:39
  • @Dev-iL getAttributes() returns a WindowManger.LayoutParams, but in my case I implicitly cast it to ViewGroup.LayoutParams because that's all I need (Effective Java, Item 52) -- I'll edit the question to reflect this – jmaculate Dec 13 '14 at 15:12
  • 1
    If you need to cast it again to `android.view.WindowManager.LayoutParams`, it's useless to use `ViewGroup.LayoutParams` three lines above... You don't gain any flexibility here. Whatever, thank you for this good answer! – Kevin Robatel Oct 07 '15 at 14:51
  • 2
    This is the best solution. You can even use a specific value of pixels along with MATCH_PARENT or WRAP_CONTENT. – Koesh Jan 12 '16 at 07:12
  • Here is the shorthand for this... `getDialog().getWindow().setLayout( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT );` – EMalik Jun 29 '16 at 17:41
  • in my case there is no difference between `params.height=ViewGroup.LayoutParams.WRAP_CONTENT` and `MATCH_PARENT` , can you suggest me a solution please? – sepehr Sep 04 '16 at 19:24
  • It takes the entire space. How to give it a margin, so that on click outside dialog it would be closed? – Saeed Neamati Jun 02 '17 at 16:13
  • @jmaculate if I want to change the height of dialogFragment dynamically, isn't onResume() too late and will cause slagish UI? I would have done it in onMeasure() if it was a fragment or an activity – Elad Benda Apr 26 '19 at 13:05
118

UPDATE 2021

For Kotlin users, I've crafted a couple of simple extension methods that will set the width of your DialogFragment to either a percentage of the screen width, or near full screen:

/**
 * Call this method (in onActivityCreated or later) to set 
 * the width of the dialog to a percentage of the current 
 * screen width.
 */
fun DialogFragment.setWidthPercent(percentage: Int) {
    val percent = percentage.toFloat() / 100
    val dm = Resources.getSystem().displayMetrics
    val rect = dm.run { Rect(0, 0, widthPixels, heightPixels) }
    val percentWidth = rect.width() * percent
    dialog?.window?.setLayout(percentWidth.toInt(), ViewGroup.LayoutParams.WRAP_CONTENT)
}

/**
 * Call this method (in onActivityCreated or later) 
 * to make the dialog near-full screen.
 */
fun DialogFragment.setFullScreen() {
    dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}

Then in your DialogFragment in or after onActivityCreated:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    setWidthPercent(85)
}

Consider the remainder of this answer for posterity.

Gotcha #13: DialogFragment Layouts

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 though, 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 OnCreateView or OnCreateDialog depends on how you intend to use the dialog.

  • If you intend to allow the DialogFragment to control the rendering of its own internal Dialog, then you are expected to override OnCreateView.
  • If you intend to manually control how the DialogFragment's Dialog will be rendered, you are expected to override OnCreateDialog.

This is possibly 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. Cool. 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 insideous.

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.LayoutParams back 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.
rmirabelle
  • 6,268
  • 7
  • 45
  • 42
  • 1
    @rmirabelle - this answer actually help, you can actually write a medium blog, and can be helpful for many. In my case I am using constraint layout and DialogFragment, so with was ignore in Android 9, below Android 9 it is working fine. I have added - "android:windowMinWidthMajor , "android:windowMinWidthMinor" in style and it started working fine. – Rahul Aug 29 '19 at 10:45
  • @Rahul https://medium.com/@rmirabelle/how-to-set-dialogfragment-width-and-height-733c5b174178?source=friends_link&sk=89b6925083afc3910c1b12f8e53b26d5 – rmirabelle Aug 29 '19 at 17:24
  • @rmirabelle Hi, First of all your answer really helped me to solve an old issue. But as a person that have to understand all, can you please explain me why if i write the code that changed the window size in 'onCreateView' instead of in 'onResume' it doesn't apply the desired width and height? It makes me crazy to do thing without understanding the reason why i'm doing them – Eitanos30 Mar 20 '20 at 22:19
  • @Eitanos30 My guess is that the `Window` object isn't available until some time AFTER `onCreateView` is called. If understanding things is important to you (as it is to me), I have some bad news for you. Android is the most incomprehensible thing ever conceived by humans. – rmirabelle Mar 21 '20 at 04:52
  • @rmirabelle, thanks :) if it is so bother you (and me too), so how can we develop for Android? – Eitanos30 Mar 21 '20 at 13:48
  • @Eitanos30, yes, dialogs in Android are craps. You can use `onActivityCreated` instead of `onResume`, if you use `onCreateView` instead of `onCreateDialog`. `onCreateView` is limited in many actions in dialogs. – CoolMind Jun 05 '20 at 10:27
  • onActivityCreated is deprecated, you should do dialog?.window?.setLayout(... ) in onViewCreated() instead. I agree that the number of LayoutParams classes is confusing, but I wouldn't just dismiss this as poor design. The various LayoutParams classes support different features depending on the View class they are defined for (e.g. LinearLayout.LayoutParams has an orientation field). – Ridcully Oct 30 '22 at 18:42
112

I got a fixed size DialogFragment defining the following in the XML main layout (LinearLayout in my case):

android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="1000dp"
android:minHeight="450dp"
Jose_GD
  • 2,279
  • 1
  • 21
  • 34
  • 4
    I found that I needed the midWidth and minHeight in Honeycomb - but not in ICS. – daveywc Apr 17 '13 at 20:35
  • 2
    This appears to work at first glance but it probably should be avoided. The view will continue off screen depending on the device width so if you have buttons in the lower right corner they won't appear. – CodyEngel Jul 11 '18 at 13:43
  • 1
    The view is NOT continuing off screen. The android system seems to make sure that the DialogFragment stays inside the view bounds (with a small margin), even if these bounds are smaller than the specified minWidth and minHeight. – Lensflare Aug 06 '18 at 09:59
  • 1
    And this seems to work even in 2021. Hat's off to Google – Rahul Shukla Sep 23 '21 at 12:38
56

One way to control your DialogFragment's width and height is to make sure its dialog respects your view's width and height if their value is WRAP_CONTENT.

Using ThemeOverlay.AppCompat.Dialog

One simple way to achieve this is to make use of the ThemeOverlay.AppCompat.Dialog style that's included in Android Support Library.

DialogFragment with Dialog:

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    Dialog dialog = new Dialog(getContext(), R.style.ThemeOverlay_AppCompat_Dialog);
    dialog.setContentView(view);
    return dialog;
}

DialogFragment with AlertDialog (caveat: minHeight="48dp"):

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_AppCompat_Dialog);
    builder.setView(view);
    return builder.create();
}

You can also set ThemeOverlay.AppCompat.Dialog as the default theme when creating your dialogs, by adding it to your app's xml theme.
Be careful, as many dialogs do need the default minimum width to look good.

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- For Android Dialog. -->
    <item name="android:dialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>

    <!-- For Android AlertDialog. -->
    <item name="android:alertDialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>

    <!-- For AppCompat AlertDialog. -->
    <item name="alertDialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>

    <!-- Other attributes. -->
</style>

DialogFragment with Dialog, making use of android:dialogTheme:

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    Dialog dialog = new Dialog(getContext());
    dialog.setContentView(view);
    return dialog;
}

DialogFragment with AlertDialog, making use of android:alertDialogTheme or alertDialogTheme (caveat: minHeight="48dp"):

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
    builder.setView(view);
    return builder.create();
}

Bonus

On Older Android APIs, Dialogs seem to have some width issues, because of their title (even if you don't set one).
If you don't want to use ThemeOverlay.AppCompat.Dialog style and your Dialog doesn't need a title (or has a custom one), you might want to disable it:

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    Dialog dialog = new Dialog(getContext());
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setContentView(view);
    return dialog;
}

Outdated answer, won't work in most cases

I was trying to make the dialog respect the width and height of my layout, without specifying a fixed size programmatically.

I figured that android:windowMinWidthMinor and android:windowMinWidthMajor were causing the problem. Even though they were not included in the theme of my Activity or Dialog, they were still being applied to the Activity theme, somehow.

I came up with three possible solutions.

Solution 1: create a custom dialog theme and use it when creating the dialog in the DialogFragment.

<style name="Theme.Material.Light.Dialog.NoMinWidth" parent="android:Theme.Material.Light.Dialog">
    <item name="android:windowMinWidthMinor">0dip</item>
    <item name="android:windowMinWidthMajor">0dip</item>
</style>
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new Dialog(getActivity(), R.style.Theme_Material_Light_Dialog_NoMinWidth);
}

Solution 2: create a custom theme to be used in a ContextThemeWrapper that will serve as Context for the dialog. Use this if you don't want to create a custom dialog theme (for instance, when you want to use the theme specified by android:dialogTheme).

<style name="Theme.Window.NoMinWidth" parent="">
    <item name="android:windowMinWidthMinor">0dip</item>
    <item name="android:windowMinWidthMajor">0dip</item>
</style>
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new Dialog(new ContextThemeWrapper(getActivity(), R.style.Theme_Window_NoMinWidth), getTheme());
}

Solution 3 (with an AlertDialog): enforce android:windowMinWidthMinor and android:windowMinWidthMajor into the ContextThemeWrapper created by the AlertDialog$Builder.

<style name="Theme.Window.NoMinWidth" parent="">
    <item name="android:windowMinWidthMinor">0dip</item>
    <item name="android:windowMinWidthMajor">0dip</item>
</style>
@Override
public final Dialog onCreateDialog(Bundle savedInstanceState) {
    View view = new View(); // Inflate your view here.
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setView(view);
    // Make sure the dialog width works as WRAP_CONTENT.
    builder.getContext().getTheme().applyStyle(R.style.Theme_Window_NoMinWidth, true);
    return builder.create();
}
jpmcosta
  • 1,752
  • 15
  • 24
  • 5
    I really don't know why the hell this is not the accepted answer. This is literally THE only answer that works and isn't a hack (I'm talking mostly for your 1st solution). – Bogdan Zurac Oct 05 '15 at 10:26
  • 1
    unfortunately found this only after spending an hour figuring how to solve! – brainvision Mar 03 '16 at 21:40
  • Solution 3 saves my life. Thank you so much – Simon Jan 30 '17 at 02:13
  • I was able to reproduce your problem on older Android APIs. Added some alternatives that might help you. – jpmcosta Dec 15 '17 at 20:09
  • Solution 1 worked for me. i just used `Theme.MaterialComponents.Light.Dialog` as parent and used this style in the constructor of `MaterialAlertDialogBuilder`. Stumbled upon your answer after a research of 1 hour. Thanks and thumbs up. – Shahood ul Hassan Jul 15 '20 at 09:23
52

The only thing that worked in my case was the solution pointed here: http://adilatwork.blogspot.mx/2012/11/android-dialogfragment-dialog-sizing.html

Snippet from Adil blog post:

@Override
public void onStart()
{
  super.onStart();

  // safety check
  if (getDialog() == null)
    return;

  int dialogWidth = ... // specify a value here
  int dialogHeight = ... // specify a value here

  getDialog().getWindow().setLayout(dialogWidth, dialogHeight);

  // ... other stuff you want to do in your onStart() method
}
Rodrigo
  • 620
  • 6
  • 7
  • +1 `getDialog().getWindow().setLayout(dialogWidth, dialogHeight); ` works perfectly for a DialogFragment. But I don't understand the safety check. why we have to check `null`? – mrtpk Sep 09 '16 at 06:30
  • 3
    @2943 - simply because there's no guarantee that the `Dialog` (a child of the `DialogFragment`) will be available at the time it's requested. It's possible that Android will return null when we call `getDialog()`. – rmirabelle Jan 05 '17 at 18:02
  • @mirabelle if you are withing the onStart callback of the dialog how the dialog can be null? – rommex Jul 21 '17 at 06:51
14

When I need to make the DialogFragment a bit wider I'm setting minWidth:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minWidth="320dp"
    ... />
Andrew
  • 36,676
  • 11
  • 141
  • 113
11

I don't see a compelling reason to override onResume or onStart to set the width and height of the Window within DialogFragment's Dialog -- these particular lifecycle methods can get called repeatedly and unnecessarily execute that resizing code more than once due to things like multi window switching, backgrounding then foregrounding the app, and so on. The consequences of that repetition are fairly trivial, but why settle for that?

Setting the width/height instead within an overridden onActivityCreated() method will be an improvement because this method realistically only gets called once per instance of your DialogFragment. For example:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    Window window = getDialog().getWindow();
    assert window != null;

    WindowManager.LayoutParams layoutParams = window.getAttributes();
    layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
    window.setAttributes(layoutParams);
}

Above I just set the width to be match_parent irrespective of device orientation. If you want your landscape dialog to not be so wide, you can do a check of whether getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT beforehand.

N1hk
  • 880
  • 10
  • 10
6

The dimension in outermost layout doesn't work in dialog. You can add a layout where set dimension below the outermost.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<LinearLayout
    android:layout_width="xxdp"
    android:layout_height="xxdp"
    android:orientation="vertical">

</LinearLayout>

Kelly
  • 61
  • 1
  • 1
6

In my case DialogFragment occupied full activity size like a Fragment. The DialogFragment was based on XML-layout, not AlertDialog. My mistake was adding the dialog fragment to FragmentManager as a usual fragment:

fragmentManager?.beginTransaction()?.run {
    replace(R.id.container, MyDialogFragment.newInstance(), MyDialogFragment.TAG)
    addToBackStack(MyDialogFragment.TAG)
}?.commitAllowingStateLoss()

Instead I need to show the dialog fragment:

val dialogFragment = MyDialogFragment.newInstance()
fragmentManager?.let { dialogFragment.show(it, MyDialogFragment.TAG) }

After some editing (I have ViewPager2 in the layout) the dialog fragment became too narrow:

enter image description here

I used the solution of N1hk:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)

    dialog?.window?.attributes?.width = ViewGroup.LayoutParams.MATCH_PARENT
    dialog?.window?.attributes?.height = ViewGroup.LayoutParams.MATCH_PARENT
}

Now it has defined width and height, not full activity size.

I want to say about onCreateView and onCreateDialog. If you have a dialog fragment based on layout, you can use any of these 2 methods.

  1. If you use onCreateView, then you should use onActivityCreated to set width.

  2. If you use onCreateDialog instead of onCreateView, you can set parameters there. onActivityCreated won't be needed.

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { super.onCreateDialog(savedInstanceState)

     val view = activity?.layoutInflater?.inflate(R.layout.your_layout, null)
    
     val dialogBuilder = MaterialAlertDialogBuilder(context!!).apply { // Or AlertDialog.Builder(context!!).apply
         setView(view)
         // setCancelable(false)
     }
    
     view.text_view.text = "Some text"
    
     val dialog = dialogBuilder.create()
     // You can access dialog.window here, if needed.
    
     return dialog
    

    }

CoolMind
  • 26,736
  • 15
  • 188
  • 224
  • You saved my day, setting width in onActivityCreated worked for me. – Hagar Magdy Jun 24 '20 at 20:49
  • 1
    I'm using fragments, for me I used in onViewCreated like: `override fun onViewCreated(view: View, savedInstanceState: Bundle?) { dialog?.window?.attributes?.width = ViewGroup.LayoutParams.MATCH_PARENT dialog?.window?.attributes?.height = ViewGroup.LayoutParams.MATCH_PARENT` And it wouldn't work without the height too – C. Hellmann Sep 21 '20 at 19:34
  • @C.Hellmann, thank you! Agree, probably this behaviour has changed in API 30, I will update the answer. – CoolMind Sep 21 '20 at 22:24
5

I fixed it setting the root element layout parameters.

int width = activity.getResources().getDisplayMetrics().widthPixels;
int height = activity.getResources().getDisplayMetrics().heightPixels;
content.setLayoutParams(new LinearLayout.LayoutParams(width, height));
Erdem OLKUN
  • 51
  • 1
  • 3
5

Here's a way to set DialogFragment width/height in xml. Just wrap your viewHierarchy in a Framelayout (any layout will work) with a transparent background.

A transparent background seems to be a special flag, because it automatically centers the frameLayout's child in the window when you do that. You will still get the full screen darkening behind your fragment, indicating your fragment is the active element.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/transparent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:background="@color/background_material_light">

      .....
NameSpace
  • 10,009
  • 3
  • 39
  • 40
  • I'm going to give this a try because if it works consistently, it's a VASTLY superior approach to coding part of the layout in XML and part of it in code. Thanks – rmirabelle Jan 05 '17 at 14:24
  • I like the idea of this approach, but when tested, it yields a different layout than simply changing height and width programmatically. For instance, the overall width is forcibly reduced to the max width afforded by an AlertDialog (presumably because of Android styles). When I just set w and h via code, the AlertDialog style is overruled. This may fit many needs however and is a fine idea. Long live the worst SDK in history. – rmirabelle Jan 05 '17 at 14:39
  • Worked great for onCreateView, until I wanted to change the inner width to match_parent... – tudor Apr 05 '19 at 19:59
5

You can use percentage for width.

<style name="Theme.Holo.Dialog.MinWidth">
<item name="android:windowMinWidthMajor">70%</item>

I used Holo Theme for this example.

StefanoM5
  • 1,327
  • 1
  • 24
  • 34
4

Here is kotlin version

    override fun onResume() {
        super.onResume()

        val params:ViewGroup.LayoutParams = dialog.window.attributes
        params.width = LinearLayout.LayoutParams.MATCH_PARENT
        params.height = LinearLayout.LayoutParams.MATCH_PARENT
        dialog.window.attributes = params as android.view.WindowManager.LayoutParams
    }
Qadir Hussain
  • 8,721
  • 13
  • 89
  • 124
3

You can below code to set layout width and height from java.

final AlertDialog alertDialog  = alertDialogBuilder.create();
final WindowManager.LayoutParams WMLP = alertDialog.getWindow().getAttributes();

WMLP.gravity = Gravity.TOP;
WMLP.y = mActionBarHeight;
WMLP.x = getResources().getDimensionPixelSize(R.dimen.unknown_image_width);

alertDialog.getWindow().setAttributes(WMLP);
alertDialog.show();
Ziem
  • 6,579
  • 8
  • 53
  • 86
Ruchit Mittal
  • 312
  • 1
  • 9
3

Set the Parent layout of Custom dialogue layout to RelativeLayout, get common width and height automatically .

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
vishnuc156
  • 940
  • 12
  • 10
  • This worked for me. I wanted to use a ConstraintLayout to lay out the controls in my dialog so I used a RelativeLayout for the root layout and then put a ConstraintLayout directly inside it. This gave me a normal sized dialog. When I put the ConstraintLayout as the root without changing anything else then the dialog width imploded to not very wide! – leafcutter Nov 08 '19 at 18:30
3

Easy and solid:

@Override
    public void onResume() {
        // Sets the height and the width of the DialogFragment
        int width = ConstraintLayout.LayoutParams.MATCH_PARENT;
        int height = ConstraintLayout.LayoutParams.MATCH_PARENT;
        getDialog().getWindow().setLayout(width, height);

        super.onResume();
    }
3

This will work perfectly.

@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);
}
Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
Kishore Reddy
  • 2,394
  • 1
  • 19
  • 15
3

None of the other answers worked for me. It was solved for me only be creating a style where you can choose percentage of the screen that you want your dialog to take:

<style name="RelativeDialog" parent="android:style/Theme.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">true</item>
    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
    <item name="windowFixedWidthMajor">90%</item>
    <item name="windowFixedWidthMinor">90%</item>
    <item name="android:windowMinWidthMajor">90%</item>
    <item name="android:windowMinWidthMinor">90%</item>
    <item name="android:colorBackgroundCacheHint">@null</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowAnimationStyle">@android:style/Animation</item>
</style>

Than just set this style to the dialog like:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStyle(STYLE_NO_TITLE, R.style.RelativeDialog)
}
bmilovanovic
  • 149
  • 1
  • 5
3

I took @rmirabella 's answer and updated it to also deal with height:

private fun DialogFragment.setSize(widthPercentage: Int, heightPercentage: Int) {
    val newWidth = widthPercentage.toFloat() / 100
    val newHeight = heightPercentage.toFloat() / 100
    val dm = Resources.getSystem().displayMetrics
    val rect = dm.run { Rect(0, 0, widthPixels, heightPixels) }
    val percentWidth = rect.width() * newWidth
    val percentHeight = rect.height() * newHeight
    dialog?.window?.setLayout(percentWidth.toInt(), percentHeight.toInt())
}

Then in your DialogFragment in or after onStart():

override fun onStart() {
    super.onStart()
    setSize(
        widthPercentage = 100,
        heightPercentage = 80
    )
}
Robin
  • 704
  • 8
  • 24
2

I create the dialog using AlertDialog.Builder so I used Rodrigo's answer inside a OnShowListener.

dialog.setOnShowListener(new OnShowListener() {

            @Override
            public void onShow(DialogInterface dialogInterface) {
                Display display = getWindowManager().getDefaultDisplay();
                DisplayMetrics outMetrics = new DisplayMetrics ();
                display.getMetrics(outMetrics);
                dialog.getWindow().setLayout((int)(312 * outMetrics.density), (int)(436 * outMetrics.density));
            }

        });
Jorge Garcia
  • 680
  • 6
  • 12
  • (Mainly for future readers:) See comment by `Snicolas` in the discussion of "`DialogFragment` vs `AlertDialog`" in http://stackoverflow.com/a/7979823/3372061 . – Dev-iL Dec 13 '14 at 12:46
2

Working on Android 6.0, ran into the same issue. AlertDialog would default to predefined width set in the theme regardless of the actual width set in the custom view's root Layout. I was able to get it to set properly adjusting the width of the loading_message TextView. Without investigating further, it seems that sizing the actual elements and having the root Layout wrap around them makes it work as expected. Below is an XML layout of a loading dialog which sets width of the the dialog correctly. Using the this library for the animation.

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/custom_color"
    android:padding="@dimen/custom_dimen">
    <com.github.rahatarmanahmed.cpv.CircularProgressView
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/progress_view"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_centerHorizontal="true"
        app:cpv_color="@color/white"
        app:cpv_animAutostart="true"
        app:cpv_indeterminate="true" />
    <TextView
        android:id="@+id/loading_message"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/progress_view"
        android:layout_centerHorizontal="true"
        android:gravity="center"
        android:textSize="18dp"
        android:layout_marginTop="@dimen/custom_dimen"
        android:textColor="@color/white"
        android:text="@string/custom_string"/>
</RelativeLayout>
C0D3LIC1OU5
  • 8,600
  • 2
  • 37
  • 47
2

Add to your FragmentDialog:

public void onResume() {
    Window window = getDialog().getWindow();
    Point size = new Point();
    Display display = window.getWindowManager().getDefaultDisplay();
    display.getSize(size);
    window.setLayout( (int)(size.x * 0.9), WindowManager.LayoutParams.WRAP_CONTENT );
    window.setGravity( Gravity.CENTER );
    super.onResume();
}
RonTLV
  • 2,376
  • 2
  • 24
  • 38
1

In my case it was caused by align_parentBottom="true" given to a view inside a RelativeLayout. Removed all the alignParentBottom's and changed all the layouts to vertical LinearLayouts and problem gone.

mehmet6parmak
  • 4,777
  • 16
  • 50
  • 71
1

One of the earlier solutions almost worked. I tried something slightly different and it ended up working for me.

(Make sure you look at his solution) This was his solution.. Click Here It worked except for: builder.getContext().getTheme().applyStyle(R.style.Theme_Window_NoMinWidth, true);

I changed it to

 @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {


        // Use the Builder class for convenient dialog construction
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        // Get layout inflater
        LayoutInflater layoutInflater = getActivity().getLayoutInflater();

        // Set layout by setting view that is returned from inflating the XML layout
        builder.setView(layoutInflater.inflate(R.layout.dialog_window_layout, null));


        AlertDialog dialog = builder.create();

        dialog.getContext().setTheme(R.style.Theme_Window_NoMinWidth);

The last line is whats different really.

TheAppFoundry
  • 93
  • 1
  • 9
1

This is the simplest solution

The best solution I have found is to override onCreateDialog() instead of onCreateView(). setContentView() will set the correct window dimensions before inflating. It removes the need to store/set a dimension, background color, style, etc in resource files and setting them manually.

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = new Dialog(getActivity());
    dialog.setContentView(R.layout.fragment_dialog);

    Button button = (Button) dialog.findViewById(R.id.dialog_button);
    // ...
    return dialog;
}
parkgrrr
  • 738
  • 7
  • 12
0
@Override
public void onStart() {
    super.onStart();
    Dialog dialog = getDialog();
    if (dialog != null)
    {
        dialog.getWindow().setLayout(-1, -2);
        dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
        Window window = getDialog().getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.dimAmount = 1.0f;
        window.setAttributes(params);
        window.setBackgroundDrawableResource(android.R.color.transparent);
    }
}
0

Use RelativeLayout as a parent for DialogFragment

Sohaib Khan
  • 517
  • 5
  • 9
0
public void onResume() {

    Window window = Objects.requireNonNull(getDialog()).getWindow();
    Point size = new Point();
    assert window != null;
    Display display = window.getWindowManager().getDefaultDisplay();
    display.getSize(size);
    window.setLayout( (int)(size.x * 0.9), (int) (size.y * 0.75));
    window.setGravity( Gravity.CENTER );
    super.onResume();
    

}
  • Please add a sentence or two to explain what is different about your answer here as compared to other answers to this thread. Thanks. – Adil Hussain Sep 18 '22 at 08:49
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 27 '22 at 13:26
-4

To get a Dialog that covers almost the entire scree: First define a ScreenParameter class

public class ScreenParameters
{
    public static int Width;
    public static  int Height;

    public ScreenParameters()
    {
        LayoutParams l = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
        Width= l.width;
        Height = l.height;
    }
}

Then you have to call the ScreenParamater before your getDialog.getWindow().setLayout() method

@Override
public void onResume()
{
    super.onResume();
    ScreenParameters s = new ScreenParameters();
    getDialog().getWindow().setLayout(s.Width , s.Height);
}
Toye_Brainz
  • 100
  • 7