Подтвердить что ты не робот

Диалоговые кнопки с длинным текстом, не обертывающим/выжатым - материальная тема на android 5.0 lollipop

Оптимизируя приложение для материальной темы на леденец, я сталкиваюсь с этой неприятной проблемой:

Всякий раз, когда в диалоговом окне есть длинный текст, это не соответствует ширине панели кнопок, текст не обернут в несколько строк для этих кнопок, как в предыдущих темах. Вместо этого следующие кнопки выжимаются из диалога, будучи недоступными (см. Рисунок ниже).

Снимок экрана: http://s29.postimg.org/3vqp884cn/dialogs_light_holo_material.png

Я потратил много времени на эту проблему, и единственная тема, касающаяся этого, которую я могу найти в Интернете, такова: https://code.google.com/p/android/issues/detail?id=78302

Итак, я беру совет и задаю этот вопрос здесь.

То, что я пробовал, просматривает исходный код (кнопки определяются с maxLines = 2) и меняют разные параметры на buttonBarStyle и buttonBarButtonStyle, но без успеха.

Я ищу простое решение стиля и не хочу использовать сторонние библиотеки из-за этого.

Может ли это быть проблемой эмулятора? Я так не думаю.

Помощь очень ценится. Спасибо заранее.

Edit: Чтобы следить, см. Мой собственный ответ от 3 декабря, который не является решением.

4b9b3361

Ответ 1

Подводя итог этой теме всем, кто интересуется:

Тема Android Material, похоже, содержит ошибку с автоматическим диапазоном ширины кнопок в диалоговом окне предупреждений.

Если у вас есть, например, 3 кнопки, одна из которых имеет более одного слова, положительная кнопка, скорее всего, будет выжата из диалогового окна справа, вместо кнопки с несколькими словами, которые будут обернуты несколькими строками, так что все кнопки вписываются в панель кнопок, как это делает основная тема/голограмма.

Решения не могут быть реализованы только путем внесения изменений в buttonBarStyle и/или buttonBarButtonStyle, поскольку их стили не ограничивают тексты кнопок, которые по умолчанию завернуты в несколько строк.

Конечно, в диалоговых окнах Material theme больше пространства, чем в других темах в целом, из-за шапок, смелости и щедрых дополнений и фона, но это не является источником проблемы, оно просто заставляет его казаться раньше, чем если бы стиль потребовалось меньше места.

Единственный способ решить эту проблему, похоже, дает вашим кнопкам более короткие заголовки, если вы не хотите стираться от внешнего вида Material (например, уменьшать размер текста кнопки и/или устанавливать allCaps на false).

Ответ 2

Это может быть исправлено с помощью кнопок со стрелками вместо кнопок строк. Здесь мое обходное решение о том, как это можно сделать с помощью AppCompat lib:

код      import 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
        }

Стиль

<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>

Результат

Stacked Alert Dialog

Ответ 3

Следование - Поскольку я не могу опубликовать более двух ссылок из-за репутации моих новичков, я должен опубликовать ответ на свой вопрос, а не редактировать его.

Ниже показано, как я пытался стилизовать кнопки с помощью buttonBarStyle и buttonBarButtonStyle для достижения любого улучшения - см. результаты здесь: http://s12.postimg.org/uyp0p0e6l/dialog_material_button_fix_tests_1.png

к сожалению, это, очевидно, нежелательные решения.

<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>

Ответ 4

используйте следующий код, пусть кнопки справа и вертикальное расположение

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) {

            }
        }
    });

Ответ 5

Быстрый soln, который не является динамическим, заключается в том, чтобы добавить \n, чтобы сломать длинную строку вверх

Ответ 6

Вот обходной путь, который я придумал, с помощью связанного ответа от Andrey T (fooobar.com/info/165974/...):

Сначала вы создаете метод утилиты, который будет обертывать кнопки только в том случае, если их нужно обернуть:

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);
                }
            }
        });
    }

Вы можете добавить дополнительную обработку ошибок (т.е. try/catch) и настроить ее по мере необходимости.

Теперь вы вызываете этот метод утилиты, когда отображается диалог:

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

Это делает трюк и будет только обертывать кнопки, если это необходимо. Я использую его повсюду, так как даже диалоги с двумя кнопками могут потребоваться обертывание на немецком языке, а диалоги с тремя кнопками обязательно нуждаются в нем на многих языках.