android 5.0棒棒糖上长文本未包装/挤出的对话框按钮-材料主题

android 5.0棒棒糖上长文本未包装/挤出的对话框按钮-材料主题,android,button,android-alertdialog,android-5.0-lollipop,material-design,Android,Button,Android Alertdialog,Android 5.0 Lollipop,Material Design,在优化棒棒糖材质主题的应用程序时,我遇到了一个恼人的问题: 每当对话框按钮上有长文本时,总宽度与按钮栏宽度不符,这些按钮的文本不会像以前的主题那样被包装成多行。相反,以下按钮被挤出对话框,无法访问(见下图) 截图: 到目前为止,我在这个问题上花了很多时间,我在互联网上找到的唯一一个关于这个问题的话题是: 所以我在这里接受建议,在这里问这个问题 我尝试的是查看源代码(按钮定义为maxLines=2)并更改buttonBarStyle和buttonBarButtonStyle上的不同参数,但没有

在优化棒棒糖材质主题的应用程序时,我遇到了一个恼人的问题:

每当对话框按钮上有长文本时,总宽度与按钮栏宽度不符,这些按钮的文本不会像以前的主题那样被包装成多行。相反,以下按钮被挤出对话框,无法访问(见下图)

截图:

到目前为止,我在这个问题上花了很多时间,我在互联网上找到的唯一一个关于这个问题的话题是:

所以我在这里接受建议,在这里问这个问题

我尝试的是查看源代码(按钮定义为maxLines=2)并更改buttonBarStyle和buttonBarButtonStyle上的不同参数,但没有成功

我正在寻找一个简单风格的解决方案,因此不想使用第三方库

这可能只是一个模拟器问题吗?我不这么认为

非常感谢您的帮助。提前谢谢

编辑: 要跟进,请参阅12月3日我自己的答案,这不是一个解决方案。

跟进- 由于我初学者的名声,我不能发布超过两个链接,所以我不得不发布我问题的答案,而不是编辑它

下面是我如何尝试使用buttonBarStyle和buttonBarButtonStyle设置按钮样式以实现任何改进-请参见此处的结果:

不幸的是,这些显然不是可取的解决办法

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

@样式/自定义AlertDialogStyle
@样式/自定义按钮按钮样式
@样式/自定义按钮样式
匹配父项
包装内容
@空的
@空的
0dp
1.

要为感兴趣的人总结此主题:

安卓材质主题似乎有一个bug,在警报对话框中自动设置按钮宽度范围

例如,当您有3个按钮,其中一个按钮有多个单词时,正面按钮可能会从右侧的对话框中挤出,而不是将多个单词的按钮包装成多行,这样所有按钮都可以像基本主题/全息主题一样放在按钮栏中

似乎不存在仅通过对buttonBarStyle和/或buttonBarButtonStyle应用更改的解决方案,因为默认情况下,它们的样式并不限制按钮文本被包装在多行中

当然,材质主题对话框按钮通常需要比其他主题更多的空间,这是由于大写、粗体、大量的填充和背景,但这并不是问题的根源,它只是使其比样式所需空间更少时显示得更快


解决此问题的唯一方法似乎是缩短按钮标题,如果您不想改变材质的外观(如缩小按钮文本大小和/或将allCaps设置为false).

一个非动态的快速解决方案是添加\n以打断长字符串

这可以通过使用堆叠按钮而不是行按钮来解决。下面是如何使用AppCompat lib实现的解决方法:

代码 导入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>

@样式/堆叠按钮BarbuttonStyle
正确的
结果


在Andrey T()的链接答案的帮助下,我想出了一个解决方法:

首先,创建一个实用程序方法,该方法仅在需要包装按钮时才会包装按钮:

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

这样做的诀窍,将只包装按钮,如果需要的话。我到处都在使用它,因为即使是两个按钮对话框也可能需要德语包装,而三个按钮对话框肯定需要多种语言包装。

使用以下代码,让按钮位于右侧和垂直排列

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

            }
        }
    });

你试过直接在按钮对象上调用setSingleLine(false)吗?谢谢,但是我怎样才能得到AlertDialog的按钮对象?@Nikola-好的,我试过你的建议,但没有改变。此外,当我将固定宽度/权重设置为“buttonBarButtonStyle”时,它实际上会产生多行,但这显然不是一个解决方案。你可以发布你在主题中尝试设置buttonBarStyle的方法吗?@Mus请看我自己的答案。由于文本被迫在材质上使用所有大写字母,因此占用了更多空间并导致添加换行符。我知道这并不优雅,但请尝试缩短按钮标签或缩小对话框按钮的文本大小。还有,我给了你一些代表,所以在你刚开始的时候可能会很烦人:)@Mus-非常感谢这些代表。很明显,材质上的按钮由于大写、粗体、宽大的填充和背景而占据了更多的空间。但它们仍然应该像Holo(nessecary时会变宽,可能会变宽,nessecary时会断线)那样自然地表现,而不是消失。在我看来,这实际上像是一个Android/材质主题bug。如果我不想改变材质的外观和感觉,我可能不得不像穆斯提到的那样,大幅缩短几个按钮文本。太糟糕了,例如,我喜欢像“不再显示”这样的按钮文本,而不是像“隐藏”这样的按钮文本,因为它们不那么清晰。没问题,如果您的目标操作系统版本小于
21
,您可以使用“不再显示”复选框来选择要继承的父样式,我收到一条错误消息,指出该样式仅在API
21
中使用时可用,例如:
“@android:style/Widget.Material.Light.Button.Borderless.Colored”
作为父样式。这并不总是有效的,有些语言本身就有很长的翻译,即使是简单的英语作品,如OK、Continue等。这在平板电脑上看起来很糟糕,因为有足够的空间。这很有效,但
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) {

            }
        }
    });