web-dev-qa-db-ja.com

長いテキストが折り返されない/絞り出されていないダイアログボタン-Android 5.0ロリポップのマテリアルテーマ

Lollipopのマテリアルテーマ用にアプリを最適化しているときに、次の厄介な問題に遭遇しました。

ダイアログボタンに長いテキストがあり、その合計がボタンバーの幅に合わない場合は、以前のテーマのように、ボタンのテキストが複数行に折り返されることはありません。代わりに、次のボタンはダイアログから押し出され、到達できません(下の画像を参照)。

スクリーンショット: http://s29.postimg.org/3vqp884cn/dialogs_light_holo_material.png

これまでこの問題に多くの時間を費やしてきましたが、インターネットで見つけることができる唯一のトピックは次のとおりです https://code.google.com/p/Android/issues/詳細?id = 78302

そこで私はそこでアドバイスを受けて、ここでこの質問をします。

私が試したのは、ソースを調べ(ボタンはmaxLines = 2で定義されています)、buttonBarStyleとbuttonBarButtonStyleの異なるパラメーターを変更しましたが、成功しませんでした。

私はシンプルなスタイルソリューションを探しています。このため、サードパーティのライブラリを使用したくありません。

これはエミュレータの問題だけですか?私はそうは思いません。

ヘルプは大歓迎です。前もって感謝します。

編集:フォローアップするには、解決策ではない12月3日の自分の回答を参照してください。

33
sec_aw

興味のある人のためにこのトピックを要約すると:

Android Materialテーマには、警告ダイアログの自動ボタン幅スパンに関するバグがあるようです。

たとえば、3つのボタンがあり、そのうちの1つに複数のWordが含まれている場合、複数のWordが複数行に折り返されているボタンではなく、ダイアログボックスから正のボタンが右側に絞り出される可能性があります。ボタンは基本的なテーマ/ホロテーマがやっているようにボタンバーに収まります。

それらのスタイルはデフォルトで複数行に折り返されるボタンテキストを制限しないため、buttonBarStyleやbuttonBarButtonStyleに変更を適用するだけでは解決策はないようです。

確かに、マテリアルテーマのダイアログボタンは、大文字、太字、十分なパディングと背景のため、一般的に他のテーマよりも多くのスペースを必要としますが、これは問題の原因ではなく、スタイリングが少ない場合よりも早く表示されます。必要。

この問題を解決する唯一の方法は、マテリアルのルックアンドフィールからスタイルを変更したくない場合(ボタンのテキストサイズを小さくしたり、allCapsをfalseに設定したりする場合など)、ボタンのタイトルを短くすることです。

6
sec_aw

これは、行ボタンの代わりにスタックボタンを使用することで修正できます。ここでは、AppCompat libを使用してそれを達成する方法を私の回避策を示します。

Code 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

19
Andrey T

フォローアップ-初心者の評判のため、2つを超えるリンクを投稿することはできないため、質問を編集するのではなく、回答を投稿する必要があります。

以下は、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>
14
sec_aw

次のコードを使用して、ボタンを右側に配置し、垂直に配置します

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

            }
        }
    });
3
wayne

動的でない迅速な解決策は、\ nを追加して長い文字列を分割することです

2
user1634451

Andrey Tからのリンクされた回答( https://stackoverflow.com/a/29662638/1317564 )の助けを借りて、私が思いついた回避策は次のとおりです。

最初に、ボタンをラップする必要がある場合にのみボタンをラップするユーティリティメソッドを作成します。

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/catchesなど)を追加して、必要に応じてさらにカスタマイズできます。

ここで、ダイアログが表示されたときにこのユーティリティメソッドを呼び出します。

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

これはトリックであり、必要な場合にのみボタンをラップします。 2ボタンのダイアログでもドイツ語でのラッピングが必要な場合があり、3ボタンのダイアログでも多くの言語でラッピングが必要になる場合があるため、私はそれをどこでも使用しています。

2
Learn OpenGL ES