Marek M.
Marek M.

Reputation: 3951

Android - how to set dialog's outer margin

I know that this question have been asked a few times, but none of the solutions I came across worked for me, hence this topic. As the title states - I want to set dialog's outer margin:

PurchaseDetailsDialogFragment

public class PurchaseDetailsDialogFragment extends DialogFragment {

    private static final String MAX_AMOUNT = "maxAmount";

    private static final String UNIT_PRICE = "unitPrice";

    private static final String PICKUP_TIME_FROM = "pickupTimeFrom";

    private static final String PICKUP_TIME_TO = "pickupTimeTo";

    public PurchaseDetailsDialogFragment() { }

    public static PurchaseDetailsDialogFragment newInstance(int maxAmount, float unitPrice, String pickupTimeFrom, String pickupTimeTo) {
        PurchaseDetailsDialogFragment fragment = new PurchaseDetailsDialogFragment();
        Bundle args = new Bundle();

        args.putInt(MAX_AMOUNT, maxAmount);
        args.putFloat(UNIT_PRICE, unitPrice);
        args.putString(PICKUP_TIME_FROM, pickupTimeFrom);
        args.putString(PICKUP_TIME_TO, pickupTimeTo);
        fragment.setArguments(args);

        return fragment;
    }

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

        if (getArguments() != null) {
            int maxAmount = getArguments().getInt(MAX_AMOUNT);
            float unitPrice = getArguments().getFloat(UNIT_PRICE);
            String pickupFrom = getArguments().getString(PICKUP_TIME_FROM);
            String pickupTo = getArguments().getString(PICKUP_TIME_TO);
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Context context = getContext();
        FragmentPurchaseDetailsDialogBinding binding = DataBindingUtil.inflate(
                LayoutInflater.from(context),
                R.layout.fragment_purchase_details_dialog,
                null,
                false);

        binding.setDataContext(new PurchaseDetailsViewModel(context));

        AlertDialog dialog = new AlertDialog.Builder(getActivity(), R.style.DialogTheme)
                                            .setView(binding.getRoot())
                                            .create();

        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));

        return dialog;
    }

}

fragment_purchase_details_dialog

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="@drawable/dialog">

    <data>
        <variable
            name="dataContext"
            type="com.myapp.viewModels.PurchaseDetailsViewModel" />
    </data>

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="80dp"
            android:paddingTop="20dp"
            android:layout_centerHorizontal="true"
            android:background="@color/white">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/choose_amount"
                style="@style/Widget.App.PurchaseTextViewTitle" />

        </FrameLayout>

        <LinearLayout
            android:id="@+id/dialogCentralContent"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:orientation="vertical"
            android:layout_marginTop="80dp"
            android:background="@color/dirtyWhite">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="74" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="46dp"
            android:layout_centerHorizontal="true">

            <Button
                android:layout_width="44dp"
                android:layout_height="44dp"
                android:layout_marginTop="6dp"
                android:background="@drawable/button_filled"
                android:text="-"
                style="@style/Widget.App.PurchaseIncDecButton" />

            <FrameLayout
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:layout_marginLeft="8dp"
                android:layout_marginRight="8dp"
                android:background="@drawable/edittext_white_rounded">

                <EditText
                    android:layout_width="30dp"
                    android:layout_height="match_parent"
                    android:layout_marginLeft="15dp"
                    android:gravity="center_horizontal"
                    android:maxLines="1"
                    style="@style/Widget.App.PurchaseAmountEditText" />

            </FrameLayout>

            <Button
                android:layout_width="44dp"
                android:layout_height="44dp"
                android:layout_marginTop="6dp"
                android:background="@drawable/button_filled"
                android:text="+"
                style="@style/Widget.App.PurchaseIncDecButton" />

        </LinearLayout>

        <Button
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_below="@+id/dialogCentralContent"
            android:text="@string/buttonBuyText"
            android:background="@drawable/button_submit"
            style="@style/Widget.App.SubmitButton" />

    </RelativeLayout>

</layout>

Now with the above code only, my dialog takes up whole width of the screen. If I however do this, in the fragment java code:

AlertDialog dialog = new AlertDialog.Builder(getActivity(), R.style.DialogTheme) /// the rest of the code

And add a theme:

<resources>

    <style name="DialogTheme" parent="@android:style/Theme.Material.Dialog.Alert">
        <item name="android:windowMinWidthMajor">380dp</item>
        <item name="android:windowMinWidthMinor">380dp</item>
    </style>

</resources>

Then some funky stuff happens. On API23 all looks fine, while on API19 and below (didn't check apis between 19 and 23) the dialog is 100% wide and aligned to top of the screen. How to make it work the way I'd like it to?

Upvotes: 0

Views: 3546

Answers (3)

ssynhtn
ssynhtn

Reputation: 1377

<item name="android:windowMinWidthMinor">380dp</item>

this will keep the dialog width to be a mininum of 380dp, but if device width < 380dp, then the dialog will take up the whole available space

If you tested with a device with a smaller width(very likely if the device has a lower api, for example Galaxy Nexus's width is 360dp), of course it will take up the whole width.

It's better to specify the minWidth as a percentage

for your particular case, to achieve a predefined margin(without modifying the Window's layout attributes programmatically), we can set the min width to be 100%

<item name="android:windowMinWidthMinor">100%</item>

and use an inset drawble as the windowBackground, which is already the case if you are using AppCompat

<item name="android:windowBackground">@drawable/abc_dialog_material_background</item>

abc_dialog_material_background:

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetLeft="16dp"
    android:insetTop="16dp"
    android:insetRight="16dp"
    android:insetBottom="16dp">
    <shape android:shape="rectangle">
        <corners android:radius="@dimen/abc_dialog_corner_radius_material" />
        <solid android:color="@android:color/white" />
    </shape>
</inset>

Upvotes: 0

Marek M.
Marek M.

Reputation: 3951

There's one really simple solution to this. Just put your layout inside, for example a FrameLayout and set appropriate paddings on the outer layout element. Then everything is gonna look the same across all apis:

<FrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingLeft="@dimen/defaultMargin"
    android:paddingRight="@dimen/defaultMargin">

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </RelativeLayout>
</FrameLayout>

Upvotes: 2

karthik prasad
karthik prasad

Reputation: 728

Have you tried this ?

How to Build AppCompatDialog From AlertDialog.Builder or Equivalent?

It suggests you to use android.support.v7.app.AlertDialog rather than android.app.AlertDialog

So for dialogs with multiple choices try AppCompactDialog

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.DialogTheme)
                                        .setView(binding.getRoot())
                                        .create();
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
AppCompatDialog alert = builder.create();
alert.show();

I have not tried this. Let me know if this works.

Upvotes: 0

Related Questions