【问题标题】:Android: message font size in alertdialog through stylesAndroid:通过样式在警报对话框中的消息字体大小
【发布时间】:2016-02-03 14:18:56
【问题描述】:

我正在尝试通过样式更改警报对话框中消息的字体大小,但无法使其正常工作。有很多答案描述了如何做到这一点,但我发现几乎所有答案都是以编程方式完成的。我想在样式中执行一次,而不是在每个新的警报对话框中执行一次。

到目前为止我做了什么:

\AndroidSDK\platforms\android-23\data\res\layout\alert_dialog.xml 中,我看到了显示消息的 TextView:

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

\AndroidSDK\platforms\android-23\data\res\values\themes.xml我看到textAppearanceMedium属性的值为@style/TextAppearance.Medium

我创建了一个父样式为TextAppearance.AppCompat.Medium 的样式。然后将此样式应用于 AlertDialog 样式的android:textAppearanceMedium 属性,如下所示:

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

...但字体大小不会改变。怎么了?

我正在使用 AppCompat 支持库,最低 SDK 16,目标 SDK 23。

谢谢。

【问题讨论】:

    标签: android android-alertdialog android-theme android-styles


    【解决方案1】:

    AlertDialog 在 Material Theme 之前一直使用主题属性 ?android:attr/textAppearanceMedium" 来处理对话框内容。

    如果您查看AlertDialog 的源代码,它使用AlertController 来管理AlertDialog。在AlertDialog 构造函数中,我们有这个:

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

    我们可以看到AlertDialog的布局来自declare-styleable name=AlertDialog中声明的名为“layout”的属性,并在属性alertDialogStyle中定义在主题级别。

    知道,在 Material 主题中查看 alertDialogStyle,我们得到了这个
    &lt;item name="alertDialogStyle"&gt;@style/AlertDialog.Material&lt;/item&gt;

    Alert.Dialog.Material 我们得到了&lt;item name="layout"&gt;@layout/alert_dialog_material&lt;/item&gt;

    它使用的是 alert_dialog_material 而不是 alert_dialog

    alert_dialog_material 我们有相同的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" />
    

    但样式指向本地主题而不是 ?android:attr/textAppearanceMedium,这就是为什么您不能像以前那样设置消息样式。

    解决方案 1:

    我们只能以编程方式执行此操作。从对话框中获取TextViewusing 窗口并设置您想要的外观:

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

    解决方案 2:

    为了更灵活,我们可以在attrs.xml中定义一个属性

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

    在你的主题中定义属性:

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

    并在代码中使用:

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

    【讨论】:

      【解决方案2】:

      如果我们通过android源我们会发现Theme.AppCompat.Light.Dialog.Alert主题继承了alertDialogStyle:

      <item name="alertDialogStyle">@style/AlertDialog.AppCompat.Light</item>
      

      通过AlertDialog.AppCompat.Light样式我们会发现它使用默认布局:

      <item name="android:layout">@layout/abc_alert_dialog_material</item>
      

      进一步调查来源,特别是布局@layout/abc_alert_dialog_material,我们将看到TextView id android:id="@android:id/message"(这是消息TextView)使用样式TextAppearance.AppCompat.Subhead

      <TextView
          android:id="@android:id/message"
          style="@style/TextAppearance.AppCompat.Subhead"
          ... />
      

      在应用程序的values/styles.xml 文件中覆盖这些样式将更改警报对话框中消息的外观:

      <style name="TextAppearance.AppCompat.Subhead" parent="Base.TextAppearance.AppCompat.Subhead">
          <item name="android:textSize">24sp</item>
          <item name="android:textColor">#ff0000</item> <!-- we can change other parameters, e.g. textColor -->
      </style>
      

      【讨论】:

      • 您的解决方案不完整。所以它不起作用。如何覆盖 textView style="@style/TextAppearance.AppCompat.Subhead" ?
      • 它按预期工作。 style="@style/TextAppearance.AppCompat.Subhead 是自定义样式,通过创建新样式并将其指定为 parent="@style/TextAppearance.AppCompat.Subhea"> 来像其他样式一样覆盖它。