Pregunta Botones de diálogo con texto largo que no se envuelve / estrujado - tema material en Android 5.0 lollipop


Al optimizar una aplicación para el tema material en lollipop, me encuentro con este problema molesto:

Siempre que haya texto largo en los botones de diálogo, eso no se ajusta al ancho total de la barra de botones, el texto no está envuelto en múltiples líneas para esos botones como en los temas anteriores. En su lugar, los siguientes botones quedan fuera del diálogo, siendo inalcanzable (ver imagen a continuación).

Captura de pantalla: http://s29.postimg.org/3vqp884cn/dialogs_light_holo_material.png

He dedicado mucho tiempo a este problema hasta ahora y el único tema que pude encontrar en Internet es este: https://code.google.com/p/android/issues/detail?id=78302

Así que estoy tomando el consejo y hago esta pregunta aquí ..

Lo que he intentado es buscar en la fuente (los botones se definen con maxLines = 2) y cambiar los diferentes parámetros en buttonBarStyle y buttonBarButtonStyle pero sin éxito.

Estoy buscando una solución de estilo simple y no quiero usar bibliotecas de terceros debido a esto.

¿Puede ser solo un problema de emulador? No lo creo.

Se aprecia mucho la ayuda. Gracias por adelantado.

Editar: Para seguir, vea mi propia respuesta del 3 de diciembre, que no es una solución.


32
2017-11-28 11:05


origen


Respuestas:


Esto podría solucionarse con el uso de botones apilados en lugar de botones de filas. Aquí mi solución acerca de cómo se puede lograr con el uso de AppCompat lib:

Código         importar android.support.v7.app.AlertDialog;

    AlertDialog.Builder builder;
    builder = new AlertDialog.Builder(context, R.style.StackedAlertDialogStyle);
    builder.setTitle("Title");
    builder.setMessage("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc dignissim purus eget gravida mollis. Integer in auctor turpis. Morbi auctor, diam eget vestibulum congue, quam arcu pulvinar dui, blandit egestas erat enim non ligula." +
            " Nunc quis laoreet libero. Aliquam consectetur nibh eu arcu eleifend efficitur.");
    builder.setPositiveButton("Positive Button", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
        }
    });
    builder.setNeutralButton("Neutral Button", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
        }
    });
    builder.setNegativeButton("Cancel Button", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
        }
    });
    AlertDialog alertDialog = builder.create();
    alertDialog.show();
        try{
            final Button button = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
            LinearLayout linearLayout = (LinearLayout) button.getParent();
            linearLayout.setOrientation(LinearLayout.VERTICAL);
        } catch(Exception ex){
            //ignore it
        }

Estilo

<style name="StackedAlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
    <item name="buttonBarButtonStyle">@style/StackedButtonBarButtonStyle</item>
</style>

<style name="StackedButtonBarButtonStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
    <item name="android:layout_gravity">right</item>
</style>

Resultado

Stacked Alert Dialog


18
2017-07-10 20:49



Siguiendo - Como no puedo publicar más de dos enlaces debido a mi reputación de principiante, tengo que publicar una respuesta a mi pregunta en lugar de editarla.

A continuación se muestra cómo intenté aplicar estilo a los botones usando buttonBarStyle y buttonBarButtonStyle para lograr cualquier mejora: vea los resultados aquí: http://s12.postimg.org/uyp0p0e6l/dialog_material_button_fix_tests_1.png

Desafortunadamente, obviamente esas no son soluciones deseables.

<resources>
    <style name="AppBaseTheme" parent="android:Theme.Material.Light">
        <!-- AlertDialog Style override in order to try to fix non line breaking buttons -->
        <item name="android:alertDialogTheme">@style/CustomAlertDialogStyle</item>
    </style>  

    <style name="CustomAlertDialogStyle" parent="android:Theme.Material.Light.Dialog.Alert">
        <item name="android:buttonBarButtonStyle">@style/CustomButtonBarButtonStyle</item>
        <item name="android:buttonBarStyle">@style/CustomButtonBarStyle</item>
    </style>

    <style name="CustomButtonBarStyle" parent="@android:style/Widget.Material.Light.ButtonBar.AlertDialog">
        <!-- Making sure, the button bar uses parent width and is not restricted in height -->
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:height">@null</item>
        <item name="android:minHeight">@null</item>
    </style>

    <style name="CustomButtonBarButtonStyle" parent="@android:style/Widget.Material.Light.Button.Borderless.Colored">
        <!-- Setting the weight as follows should result in equally wide buttons filling the alert dialog width,
            but instead they span further out of the dialog, breaking in multiple lines though -->
        <item name="android:layout_width">0dp</item>
        <item name="android:layout_weight">1</item>
        <!-- setting a fixed width as follows results in narrow buttons with line breaks, but of course this is not a solution -->
        <!-- <item name="android:width">100dp</item> -->
    </style>

</resources>

14
2017-12-03 21:18



Para resumir este tema para cualquier persona interesada:

El tema Material de Android parece tener un error con el ancho de botón automático en los diálogos de alerta.

Cuando tiene, por ejemplo, 3 botones, uno de los cuales tiene más de una palabra, el botón positivo probablemente será presionado fuera del diálogo a la derecha, en lugar del botón con más de una palabra envuelto en varias líneas, de modo que todo los botones se ajustan en la barra de botones como lo está haciendo el tema básico / holo theme.

No parece haber soluciones únicamente aplicando cambios a buttonBarStyle y / o ButtonBarButtonStyle, ya que sus estilos no están restringiendo los textos de los botones envueltos en múltiples líneas de manera predeterminada.

Claro, los botones de diálogo del tema Material requieren más espacio que en otros temas en general, debido a mayúsculas, audacia y relleno abundante y fondo, pero esa no es la fuente del problema, solo lo hace aparecer antes que si el diseño tuviera menos espacio requiriendo

La única forma de resolver este problema parece ser otorgando a los botones títulos más cortos, si no desea alejarse del aspecto y la sensación del Material (como reducir el tamaño del texto del botón y / o configurar todas las Capas en falso).


6
2017-12-15 11:06



use el siguiente código, deje los botones en la disposición derecha y vertical

alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {
            try {
                LinearLayout linearLayout = (LinearLayout) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).getParent();
                if (linearLayout != null) {
                    linearLayout.setOrientation(LinearLayout.VERTICAL);
                    linearLayout.setGravity(Gravity.RIGHT);
                }
            } catch (Exception ignored) {

            }
        }
    });

3
2018-02-24 08:33



Una solución rápida que no es dinámica es agregar \ n para romper la cadena larga


2
2018-04-15 23:18



Aquí hay una solución que se me ocurrió, con la ayuda de la respuesta vinculada de Andrey T (https://stackoverflow.com/a/29662638/1317564)

En primer lugar, crea un método de utilidad que ajustará los botones solo si es necesario envolverlos:

public static void applyWorkaroundForButtonWidthsTooWide(Button dialogButton) {
        if (dialogButton == null)
            return;
        if (!(dialogButton.getParent() instanceof LinearLayout))
            return;            

        // Workaround for buttons too large in alternate languages.
        final LinearLayout linearLayout = (LinearLayout) dialogButton.getParent();
        linearLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop,
                                       int oldRight, int oldBottom) {
                if (right - left > 0) {
                    final int parentWidth = linearLayout.getWidth();
                    int childrenWidth = 0;
                    for (int i = 0; i < linearLayout.getChildCount(); ++i)
                        childrenWidth += linearLayout.getChildAt(i).getWidth();

                    if (childrenWidth > parentWidth) {
                        // Apply stacked buttons
                        linearLayout.setOrientation(LinearLayout.VERTICAL);
                        linearLayout.setPadding(linearLayout.getPaddingLeft(), 0, linearLayout.getPaddingRight(),
                                linearLayout.getPaddingBottom());
                        for (int i = 0; i < linearLayout.getChildCount(); ++i) {
                            if (linearLayout.getChildAt(i) instanceof Button) {
                                final Button child = (Button) linearLayout.getChildAt(i);
                                child.setGravity(Gravity.END | Gravity.CENTER_VERTICAL);
                                final LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) child.getLayoutParams();
                                params.width = LinearLayout.LayoutParams.MATCH_PARENT;
                                params.gravity = Gravity.END;
                                child.setLayoutParams(params);
                            } else if (linearLayout.getChildAt(i) instanceof Space) {
                                linearLayout.removeViewAt(i--);
                            }
                        }
                    }

                    linearLayout.removeOnLayoutChangeListener(this);
                }
            }
        });
    }

Puede agregar la administración de errores adicionales (es decir, try / catch) y personalizarlo más según corresponda.

Ahora, llama a este método de utilidad cuando se muestra el cuadro de diálogo:

dialog.setOnShowListener(new DialogInterface.OnShowListener() {
                @Override
                public void onShow(DialogInterface dialogInterface) {
                    MaterialAlertDialogUtils.applyWorkaroundForButtonWidthsTooWide(dialog.getButton(AlertDialog.BUTTON_POSITIVE));
                }
            });

Esto hace el truco y solo envolverá los botones si es necesario. Lo he estado usando en todas partes, ya que incluso los diálogos de dos botones pueden necesitar envolverse en alemán y los diálogos de tres botones seguramente lo necesitan en muchos idiomas.


2
2017-08-14 02:48