Android: message font size in alertdialog through

2019-01-26 16:26发布

问题:

I'm trying to change font size of message in alert dialog through styles but I can't make it work. There is a lot of answers describing how to do this but almost all of them I found do it programmatically. I want to do this once in styles, not with every new alertdialog.

What I've done so far:

In \AndroidSDK\platforms\android-23\data\res\layout\alert_dialog.xml I see the TextView that is showing the message:

<TextView android:id="@+id/message"
    style="?android:attr/textAppearanceMedium"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="5dip" />

In \AndroidSDK\platforms\android-23\data\res\values\themes.xml I see that the value of textAppearanceMedium attribute is @style/TextAppearance.Medium.

I've created a following style of which the parent is TextAppearance.AppCompat.Medium. This style is then applied to android:textAppearanceMedium attribute of AlertDialog's style as follows:

<style name="Theme.My" parent="Theme.AppCompat.Light.NoActionBar.FullScreen">
    <item name="android:alertDialogTheme">@style/Theme.My.AlertDialog</item>
</style>

<style name="Theme.My.AlertDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
    <item name="android:textAppearanceMedium">@style/MyTextAppearanceMedium</item>
</style>

<style name="MyTextAppearanceMedium" parent="TextAppearance.AppCompat.Medium">
    <item name="android:textSize">24sp</item>
</style>

...but the font size won't change. What's wrong?

I'm using AppCompat support lib, min SDK 16, target SDK 23.

Thank you.

回答1:

AlertDialog was using the theme attribute ?android:attr/textAppearanceMedium" for dialog content until Material Theme.

If you look at the source code of AlertDialog it uses an AlertControllerto manage the AlertDialog. In AlertDialog constructor we have this :

 TypedArray a = context.obtainStyledAttributes(null,
             com.android.internal.R.styleable.AlertDialog,
             com.android.internal.R.attr.alertDialogStyle, 0);

     mAlertDialogLayout = a.getResourceId(com.android.internal.R.styleable.AlertDialog_layout,
             com.android.internal.R.layout.alert_dialog);

We can see that the layout for the AlertDialogcomes from an attribute called "layout" declared in declare-styleable name=AlertDialog and defined at theme level in the attribute alertDialogStyle.

Know, looking at alertDialogStyle in Material theme we got this
<item name="alertDialogStyle">@style/AlertDialog.Material</item>

and at Alert.Dialog.Material we got <item name="layout">@layout/alert_dialog_material</item>

It's using alert_dialog_material and not alert_dialog.

In alert_dialog_material we have the same TextView

<TextView android:id="@+id/message"
                      style="@style/TextAppearance.Material.Subhead"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:paddingStart="@dimen/alert_dialog_padding_material"
                      android:paddingTop="@dimen/alert_dialog_padding_top_material"
                      android:paddingEnd="@dimen/alert_dialog_padding_material" />

but the style points to a local theme instead of ?android:attr/textAppearanceMedium and that's why you can't style the message like before.

SOLUTION 1:

We can only do this programmatically. Get the TextViewusing the window from the Dialog and set the appearance you want:

android.support.v7.app.AlertDialog d = builder.show();
TextView tv = (TextView)d.getWindow().findViewById(android.R.id.message);

SOLUTION 2:

To make it more flexible we can define an attribute in attrs.xml

<resources>
    <attr name="dialogMessageStyle" format="reference"/>
</resources>

Define the attribute in your theme:

<style name="MyStyle" ...>
    <item name="dialogMessageStyle">@style/AlertDialogMessageAppearance</item>
</style>

And set it in code using:

 TextView tv = (TextView)d.getWindow().findViewById(android.R.id.message);
            TypedArray a = getTheme().obtainStyledAttributes(new int[]{R.attr.dialogMessageStyle});
            tv.setTextAppearance(DialogActivity.this,a.getResourceId(0,0));