AppCompatDialog: unable to change text color

I am struggling with the TEXT color change in AppCompat DialogFragments.

My application uses the DARK theme ( Theme.AppCompat.NoActionBar ), but for the dialogs I want to use the LIGHT theme. I use Build Tools, Support Library and compileSdkVersion to 25, it matters.

I can change everything else in the dialog box (title, background, window background) , but not the main and accented text colors that continue to use (white) settings for a dark theme, leaving white text on a white background.

I tried dozens of solutions on similar issues here in SO, for example:

1) Easy: on 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> 

With this solution, the background style and buttons from AppCompat.Light.Dialog.Alert APPLIED, but not the color of the text, as you can see in the screenshot:

enter image description here

2) Manually specifying the AlertDialog creation style:

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

Same problem. Light background, Light text.

3) Using ContextWrapper:

  ContextThemeWrapper ctw = new ContextThemeWrapper(getActivity(), R.style.AppCompatAlertDialogStyle); AlertDialog.Builder builder = new AlertDialog.Builder(ctw); 

Nothing :( The same thing happens

4) Handing over instructions of other exotic constants, I came across a lot of posts here in SO, for example

 Theme_DeviceDefault_Light_Dialog_Alert THEME_DEVICE_DEFAULT_LIGHT 

It was just a desperate attempt, but in any case the text does not change

5) Specifying the style in the fragment, and not in the dialog box

  Dialog_Meta newFragment = new Dialog_Meta(); newFragment.setStyle(DialogFragment.STYLE_NORMAL, R.style.AppCompatAlertDialogStyle); newFragment.show(fragmentManager, TAG); 

I used this solution again in a very old version of the API, I can’t remember what the problem is, but in any case it does not solve the problem :(

Can anyone tell me what's going on?

+5
source share
1 answer

The problem is the custom View that you install on AlertDialog . Although you set a specific theme for AlertDialog in general, the View inflated by an Activity theme that does not have these overridden color attribute values.

There are several ways to solve this problem.

β€’ Create a ContextThemeWrapper around the Activity Context with a custom R.style and get LayoutInflater.from() , which.

 ContextThemeWrapper ctw = new ContextThemeWrapper(getActivity(), R.style.AppCompatAlertDialogStyle); LayoutInflater inflater = LayoutInflater.from(getActivity()); View hostView = mHostView = inflater.inflate(layoutId, null); ... 

β€’ As OP, rupps discovered , AlertDialog.Builder will already have alertDialogTheme wrapped in the Context it gave, and its getContext() will return the corresponding ContextThemeWrapper , which can be used for Inflater.

 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); LayoutInflater inflater = LayoutInflater.from(builder.getContext()); // THIS IS THE KEY View hostView = mHostView = inflater.inflate(layoutId, null); ... 

From the Google documentation AlertDialog.Builder getContext() :

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

β€’ The theme can be set as the android:theme attribute in the root directory of the View Dialog layout.

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:theme="@style/AppCompatAlertDialogStyle"> ... 

β€’ Instead of independently handling inflation, the layout identifier can be passed in the call to Builder setView() , and it will be overstated using alertDialogTheme .

However, with this method, View objects from the layout will not be available until Dialog is displayed. In DialogFragment this will be in the onStart() method.

 @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setView(R.layout.dialog); return builder.create(); } @Override public void onStart() { super.onStart(); final Dialog dialog = getDialog(); dialog.findViewById(R.id.dialog_button).setOnClickListener(...); ... } 
+2
source

Source: https://habr.com/ru/post/1258990/


All Articles