长文本对话button不包裹/挤出 – 在Android 5.0棒棒糖的材料主题

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

只要对话框button上有长文本,并不符合button栏宽度,文本就不会像以前的主题那样用多行包装。 相反,以下button被挤出对话框,无法访问(见下图)。

截图: http://s29.postimg.org/3vqp884cn/dialogs_light_holo_material.png

到目前为止,我在这个问题上花了很多时间,关于它的唯一主题是,我可以在网上find这个: https : //code.google.com/p/android/issues/detail?id = 78302

所以我在那里接受build议,在这里问这个问题..

我试过的是查看源代码(button被定义为maxLines = 2),并改变buttonBarStyle和buttonBarButtonStyle上的不同参数,但没有成功。

我正在寻找一个简单的样式解决scheme,因此不想使用第三方库。

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

非常感谢帮助。 提前致谢。

编辑:要跟进,从12月3日看我自己的回答,这不是一个解决scheme。

Solutions Collecting From Web of "长文本对话button不包裹/挤出 – 在Android 5.0棒棒糖的材料主题"

这可以通过使用堆栈button而不是行button来解决。 这里我的解决方法如何使用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> 

结果

堆叠警报对话框

跟进 – 由于我的初学者声誉,我不能发布超过两个链接,我必须发布一个答案,而不是编辑它的问题。

以下是我如何使用buttonBarStyle和buttonBarButtonStyle来设置button样式来实现任何改进 – 请参阅此处的结果: 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> 

对任何感兴趣的人总结这个话题:

Android Material主题似乎在警报对话框中具有自动button宽度跨度的错误。

例如,如果有3个button,其中一个button有多个单词,则肯定button可能会从右侧的对话框中挤出,而不是多个单词被多行包装的button,以便所有button适合在基本的主题/全息主题做button栏。

单独应用buttonBarStyle和/或buttonBarButtonStyle更改似乎没有解决scheme,因为它们的样式不限制默认情况下将button文本包装成多行。

当然,材质主题对话框button通常需要比其他主题更多的空间,这是由于大写字母,粗体字和大量的填充以及背景,但这不是问题的根源,它只是使得它看起来比样式空间更小需要。

解决这个问题的唯一方法似乎是让button缩短标题,如果你不想从Material的外观风格(比如缩小button文本大小和/或将allCaps设置为false)。

使用下面的代码,让右边的button和垂直排列

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

一个非dynamic的快速解决scheme是添加\ n来打破长串

这是一个解决方法,我想出了与Andrey T( https://stackoverflow.com/a/29662638/1317564 )链接的答案的帮助:

首先,创build一个实用程序方法,只有在需要包装button时才会包装这些button:

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

您可以添加额外的error handling(即尝试/捕获),并进一步酌情进行自定义。

现在,在显示对话框时调用该实用程序方法:

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

这样做的伎俩,只会在需要时包装button。 我一直在使用它,因为即使是两个button的对话框也可能需要用德语进行包装,而三键对话框肯定需要多种语言。