While optimizing an app for material theme on lollipop, I\'m encountering this annoying problem:
Whenever there is long text on dialog buttons, that doesn\'t fit the but
Here is a workaround I came up with, with the help of the linked answer from Andrey T (https://stackoverflow.com/a/29662638/1317564):
First, you create an utility method which will wrap the buttons only if they need to be wrapped:
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);
}
}
});
}
You can add additional error handing (i.e. try/catches) and customize this further as appropriate.
Now, you call this utility method when the dialog is shown:
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
MaterialAlertDialogUtils.applyWorkaroundForButtonWidthsTooWide(dialog.getButton(AlertDialog.BUTTON_POSITIVE));
}
});
This does the trick and will only wrap the buttons if needed. I've been using it everywhere, as even two-button dialogs may need wrapping in German and three-button dialogs surely need it in many languages.