Dialog buttons with long text not wrapping / squeezed out - material theme on android 5.0 lollipop

前端 未结 6 1405
自闭症患者
自闭症患者 2021-02-01 14:37

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

6条回答
  •  梦毁少年i
    2021-02-01 15:24

    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.

提交回复
热议问题