How to apply theme to <PreferenceScreen> elements of a <PreferenceCategory>

我与影子孤独终老i 提交于 2019-11-30 15:01:34

It's a bug in earlier Android versions (see also http://code.google.com/p/android/issues/detail?id=4611).

If I remember correctly themes aren't properly applied to a PreferenceActivity on all Android 2.x versions. One way to fix this is to set adjust the colors/fonts etc. yourself, but there is also a workaround described in the comments of the bugreport. Themes should work properly on Android 3.0 and later.

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.

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 all we have to do is override the getThemeResId() method in your Activity (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)
 */
// NOTE there is no @Override, even though it overrides the Activity method
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();
        }

As all the other answers try to solve it using the java code, this is how I did it completely using xml and without declaring my own preference class.

First I copied the complete layout for a preference from here and changed all the "@+android:id/xyz" to "@android:id/xyz". Then in my styles file, I declared a new style as:

<style name="preference">
    <item name="android:layout">@layout/source_preference</item>
</style>

Now in the AppTheme, a new entry for preference:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="android:textColor">@drawable/text_selector</item>
    <item name="android:preferenceStyle">@style/preference</item>
</style>

Now for this new layout set all the styles you want. That's it.

@Override
public boolean onPreferenceTreeClick(final PreferenceScreen preferenceScreen, final Preference preference) {
    // https://code.google.com/p/android/issues/detail?id=4611 comment #35
    if (preference instanceof PreferenceScreen && ((PreferenceScreen) preference).getDialog() != null)
        ((PreferenceScreen) preference).getDialog().getWindow().getDecorView().setBackgroundColor(Color.parseColor("#ffffff"));

    return super.onPreferenceTreeClick(preferenceScreen, preference);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!