How to stack AlertDialog buttons vertically?

Viewed 8554

I am using builder to create AlertDialogs in Android using the pattern:

AlertDialog.Builder builder = new AlertDialog.Builder(context);

builder.setTitle(...);
builder.setMessage(...);

builder.setPositiveButton(button1Text, ...);
builder.setNeutralButton(button2Text, ...);
builder.setNegativeButton(button3Text, ...);

builder.show();

Currently, only two of the buttons are displayed, because the buttons are too wide to fit in the dialog. How can I enforce the buttons to stack vertically?

I am using the Theme.AppCompat.Dialog.Alert theme, which uses ButtonBarLayout to build the buttons. According to this answer, ButtonBarLayout can stack wide buttons vertically automatically, when its mAllowStacking property is set, but it seems to default to false in my case. Is there a way I can set it to true when I build the AlertDialog?

4 Answers

I don't prefer hacks. But this strikes me immediately.

If the button text it too long to all fit horizontally, then it will automatically get laid out in a vertical column of three buttons.

Just make the button text long.

  builder.setPositiveButton("          Yes", { dialog, _ -> {} })
  builder.setNeutralButton("          May be", { dialog, _ -> {} })
  builder.setNegativeButton("          No", { dialog, _ -> {} })

This is a problem with MaterialAlertDialog as well.

I tried many solutions, but I think the best one is to override the button layout that material dialogs use. Copy paste the content of mtrl_alert_dialog_actions.xml from the material library and do the necessary changes. For example change the ButtonBarLayout to a LinearLayout with vertical orientation.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/buttonPanel"
    style="?attr/buttonBarStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fillViewport="true"
    android:scrollIndicators="top|bottom">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingStart="8dp"
        android:paddingEnd="8dp"
        android:paddingTop="2dp"
        android:paddingBottom="2dp">

        <Button
            android:id="@android:id/button1"
            style="?attr/buttonBarPositiveButtonStyle"
            android:layout_width="wrap_content"
            android:layout_gravity="center"
            android:layout_height="wrap_content"/>

        <Button
            android:id="@android:id/button2"
            style="?attr/buttonBarNegativeButtonStyle"
            android:layout_width="wrap_content"
            android:layout_gravity="center"
            android:layout_height="wrap_content"/>

        <Button
            android:id="@android:id/button3"
            style="?attr/buttonBarNeutralButtonStyle"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>

</ScrollView>

Then override the layout by adding it to res/values/refs.xml:

<resources xmlns:tools="http://schemas.android.com/tools">
    <item name="mtrl_alert_dialog_actions" type="layout" tools:override="true">@layout/mtrl_alert_dialog_actions_custom</item>
</resources>
Related