Hi all I have set the theme in the manifest file like this:
android:theme="@android:style/Theme.Light"
But I have a problem in the Preferences Activity, in the main preferences the theme shows ok, but if I get to a sub preference, the theme gets messy, it is not white as it should, it is all dark, and the font is black so you can't see much, and when I start clicking on any items they will get sometimes white as they should but revert to black soon after. This is only happens on 2.1, in both the real device and emulator. Tested on the emulator running 1.6 and it was working correctly. Here is part of the code of the preferences xml file:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:title="@string/account">
<CheckBoxPreference
android:key="enable_account"
android:title="@string/account_use"
android:summary="@string/account_summ" />
<EditTextPreference
android:key="username"
android:title="@string/login"
android:dependency="enable_account"
android:summary="@string/login_summ" />
<EditTextPreference
android:key="password"
android:title="@string/password"
android:dependency="enable_account"
android:summary="@string/password_summ"
android:password="true" />
</PreferenceScreen>
And here is a screenshot:
Any workarounds?
There's an even easier solution, if you're okay with using what seems like black magic to accomplish this...
Looking at the source of
PreferenceScreen#showDialog(Bundle)
, we see that the dialog is created using the theme resource obtained viamContext.getThemeResId()
, which is then used in aContextThemeWrapper
.This can help us substantially, because the
Context
being used in thePreferenceScreen
is actually ourPreferenceActivity
, so all we have to do is override thegetThemeResId()
method (which is hidden from the public API), to provide our custom theme, and the sub-PreferenceScreen now uses whatever custom theme resource we wanted!Note that because this method is annotated with
@hide
, we can't use the@Override
annotation that would normally be used in this case; and we also can't call to thesuper.getThemeResId()
method. If you really, really want to be able to conditionally override this and call through to the super implementation as a fallback, you'll have to use Reflection to get to the super implementation's method:Somebody just posted a workaround at http://code.google.com/p/android/issues/detail?id=4611
In a nutshell, top level preference screens seem to recognize the theme but nested ones not. So the workaround recommends creating top level PreferenceActivity for nested PreferenceScreen and then invoking this new activity via intent:
I didn't have to apply the theme to anything but the application itself.
You can also use this technique to override the styles of the inner preference screens :
This code applies the style of the main preference screen to the clicked preference screen.
At last i found out how to change theme of "PreferenceActivity" programmatically(via java code)
To change theme just do like this:
Always call
setTheme(R.style.yourtheme);
method beforesuper.onCreate(savedInstanceState);
method. By doing this it will produce result as shown below.That's all.
If yo call
setTheme(R.style.yourtheme);
method aftersuper.onCreate(savedInstanceState);
method it will produce result as shown below.Note: Themes are not recognize by nested PreferenceScreen. To apply theme to that nested PreferenceScreen you have to make an another PreferenceActivity for that nested PreferenceScreen and call
setTheme(R.style.yourtheme);
method there.This does appear to be a bug. See http://code.google.com/p/android/issues/detail?id=4611