AppCompatDialog:无法更改文本颜色

rup*_*pps 5 android android-appcompat android-theme material-design

我正在努力改变AppCompat DialogFragments的TEXT颜色.

我的应用程序使用DARK主题(Theme.AppCompat.NoActionBar),但对于对话框,我想要一个LIGHT主题.我使用Build Tools,Support Library和compileSdkVersion到25,这很重要.

我可以更改对话框上的所有其他内容(标题,背景,窗口背景),但不能更改主要和带重音的文本颜色,继续使用黑色主题的(白色)设置,从而在白色背景上生成白色文本.

我在SO中尝试了类似问题的几十种解决方案,例如:

1)简单的一个:在styles.xml上:

 <!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
    <item name="alertDialogTheme">@style/AppCompatAlertDialogStyle</item>
    <item name="android:alertDialogTheme">@style/AppCompatAlertDialogStyle</item>
</style>

<style name="AppCompatAlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
    <!-- ignored !!!! -->
    <item name="colorPrimary">#ff0000</item>
    <!-- ignored !!!! -->
    <item name="colorPrimaryDark">#ff0000</item>
    <!-- ignored !!!! -->
    <item name="colorAccent">#ff0000</item>
    <!-- ignored !!!! -->
    <item name="android:textColorPrimary">#F040FF</item>
    <!-- ignored !!!! -->
    <item name="android:textColor">#F040FF</item>

</style>
Run Code Online (Sandbox Code Playgroud)

使用此解决方案,AppCompat.Light.Dialog.AlertIS APPLIED 的背景和按钮样式,但不是您在屏幕截图中看到的文本颜色:

在此输入图像描述

2)在AlertDialog创建中手动指定样式:

    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AppCompatAlertDialogStyle);
    LayoutInflater inflater = getActivity().getLayoutInflater();
    View hostView = mHostView = inflater.inflate(layoutId, null);
Run Code Online (Sandbox Code Playgroud)

同样的问题.浅色背景,浅色文本.

3)使用ContextWrapper:

    ContextThemeWrapper ctw = new ContextThemeWrapper(getActivity(),  R.style.AppCompatAlertDialogStyle);
    AlertDialog.Builder builder = new AlertDialog.Builder(ctw);
Run Code Online (Sandbox Code Playgroud)

什么都没有:(同样的事情发生了

4)手动指定其他奇特的常量我在SO中遇到过很多帖子,比如

Theme_DeviceDefault_Light_Dialog_Alert
THEME_DEVICE_DEFAULT_LIGHT
Run Code Online (Sandbox Code Playgroud)

这只是一次绝望的尝试,但无论如何文本都没有改变

5)指定片段中的样式而不是对话框中的样式

    Dialog_Meta newFragment = new Dialog_Meta();
    newFragment.setStyle(DialogFragment.STYLE_NORMAL, R.style.AppCompatAlertDialogStyle);
    newFragment.show(fragmentManager, TAG);
Run Code Online (Sandbox Code Playgroud)

我在一个非常古老的API版本中使用此解决方案,不记得是什么问题,但无论如何,并没有解决目前的问题:(

谁能告诉我发生了什么事?

Mik*_* M. 2

这里的问题是View您在AlertDialog. AlertDialog尽管您通常为 s 设置了某个主题,但该主题View会随着Activitys 的主题而膨胀,而该主题没有那些被覆盖的颜色属性值。

\n\n

有几种方法可以解决这个问题。

\n\n

\xe2\x80\xa2使用自定义ContextThemeWrapper围绕Activity\'s创建一个,并获取该值。ContextR.styleLayoutInflater.from()

\n\n
ContextThemeWrapper ctw = new ContextThemeWrapper(getActivity(), R.style.AppCompatAlertDialogStyle);\nLayoutInflater inflater = LayoutInflater.from(getActivity());\nView hostView = mHostView = inflater.inflate(layoutId, null);\n...\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

\xe2\x80\xa2 正如 OP rupps发现的那样,AlertDialog.Builder已经将其alertDialogTheme包裹在Context给定的内容上,并且其getContext()方法将返回适当的ContextThemeWrapper,可用于 Inflater。

\n\n
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());\nLayoutInflater inflater = LayoutInflater.from(builder.getContext()); // THIS IS THE KEY\nView hostView = mHostView = inflater.inflate(layoutId, null);\n...\n
Run Code Online (Sandbox Code Playgroud)\n\n

AlertDialog.Builder来自 Google方法的文档getContext()

\n\n
/**\n* Returns a {@link Context} with the appropriate theme for dialogs created by this\n* Builder.\n* Applications should use this Context for obtaining LayoutInflaters for inflating views\n* that will be used in the resulting dialogs, as it will cause views to be inflated with\n* the correct theme.\n*\n* @return A Context for built Dialogs.\n*/\npublic Context getContext() {\n    ...\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

\xe2\x80\xa2 主题可以设置为\ 布局android:theme根上的属性ViewDialog

\n\n
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\n    android:layout_width="match_parent"\n    android:layout_height="match_parent"\n    android:orientation="vertical"\n    android:theme="@style/AppCompatAlertDialogStyle">\n    ...\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

\xe2\x80\xa2 无需自己处理膨胀,布局的 ID 可以在调用中传递BuildersetView()并且它将使用alertDialogTheme.

\n\n

但是,使用此方法时,布局中的对象在显示View之前将不可用。Dialog在 a 中DialogFragment,这将在onStart()方法中。

\n\n
@Override\npublic Dialog onCreateDialog(Bundle savedInstanceState) {\n    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());\n    builder.setView(R.layout.dialog);\n    return builder.create();\n}\n\n@Override\npublic void onStart() {\n    super.onStart();\n\n    final Dialog dialog = getDialog();\n    dialog.findViewById(R.id.dialog_button).setOnClickListener(...);\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n