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 Prefer
This does appear to be a bug. See http://code.google.com/p/android/issues/detail?id=4611
At last i found out how to change theme of "PreferenceActivity" programmatically(via java code)
To change theme just do like this:
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(R.style.Holo_Theme_Light);
super.onCreate(savedInstanceState);
}
Always call setTheme(R.style.yourtheme);
method before super.onCreate(savedInstanceState);
method. By doing this it will produce result as shown below.
That's all.
If yo call setTheme(R.style.yourtheme);
method after super.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.
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 via mContext.getThemeResId()
, which is then used in a ContextThemeWrapper
.
This can help us substantially, because the Context
being used in the PreferenceScreen
is actually our PreferenceActivity
, so all we have to do is override the getThemeResId()
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!
/**
* This is a hack to provide our own theme for the PreferenceScreen's dialog.
*
* @see android.preference.PreferenceScreen#showDialog(Bundle)
*/
public int getThemeResId() {
return R.style.Theme_MyApp_PreferenceScreen;
}
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 the super.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:
try {
((Object) this).getClass().getMethod("getThemeResId").invoke(this);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
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:
<PreferenceScreen android:key="key1"
android:title="1 Item"
android:summary="">
<intent android:action="android.intent.action.VIEW"
android:targetPackage="com.example"
android:targetClass="com.example.PreferenceActivity2"/>
</PreferenceScreen>
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 :
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
Preference preference) {
super.onPreferenceTreeClick(preferenceScreen, preference);
if (preference != null) {
if (preference instanceof PreferenceScreen) {
if (((PreferenceScreen) preference).getDialog() != null) {
((PreferenceScreen) preference)
.getDialog()
.getWindow()
.getDecorView()
.setBackgroundDrawable(
this
.getWindow()
.getDecorView()
.getBackground()
.getConstantState()
.newDrawable()
);
}
}
}
return false;
}
This code applies the style of the main preference screen to the clicked preference screen.