如何将主题应用于<preferencecategory> </preferencecategory> </preferencescreen>的<preferencescreen>元素

时间:2012-04-19 12:50:46

标签: android preferenceactivity

我有一个扩展PreferenceActivity的活动。

我的主题:android:theme =“@ android:style / Theme.Light.NoTitleBar.Fullscreen”应用于清单文件中的应用程序级别。

除了“PreferenceCategory”的“PreferenceScreen”元素之外,所有内容都获得了所需的主题。它们仍然具有默认的黑色背景。简单来说,具有父首选项屏幕的主要首选项类别屏幕正在获取主题,但如果我点击任何首选项屏幕以转到其元素首选项(EditText等等),它们就不会获得主题... < / p>

任何想法为什么会发生这种情况?

结构或preferences.xml是这样的:

<PreferenceCategory>

    <PreferenceScreen>
        <EditTextPreference>
        ...
        </EditTextPreference>
        <EditTextPreference>
        ...
        </EditTextPreference>
        ...
    </PreferenceScreen>

    <PreferenceScreen>
    ...
    </PreferenceScreen>

</PreferenceCategory>

5 个答案:

答案 0 :(得分:5)

最后我发现如何以编程方式更改主题“PreferenceActivity”(通过java代码)

改变主题只需这样:

        @Override
        public void onCreate(Bundle savedInstanceState) {
        setTheme(R.style.Holo_Theme_Light);
        super.onCreate(savedInstanceState);
        }

始终在setTheme(R.style.yourtheme);方法之前调用super.onCreate(savedInstanceState);方法。通过这样做,它将产生如下所示的结果。

enter image description here

就是这样。

如果您在setTheme(R.style.yourtheme);方法之后调用super.onCreate(savedInstanceState);方法,则会产生如下所示的结果。

enter image description here

注意:嵌套的PreferenceScreen无法识别主题。要将主题应用于嵌套的PreferenceScreen,您必须为该嵌套的PreferenceScreen制作另一个PreferenceActivity,并在那里调用setTheme(R.style.yourtheme);方法。

答案 1 :(得分:3)

这是早期Android版本中的一个错误(另请参阅http://code.google.com/p/android/issues/detail?id=4611)。

如果我没记错,所有Android 2.x版本的主题都没有正确应用于PreferenceActivity。解决这个问题的一种方法是自己设置调整颜色/字体等,但是bug报告的注释中也有一个解决方法。主题应该在Android 3.0及更高版本上正常运行。

答案 2 :(得分:2)

查看PreferenceScreen#showDialog(Bundle)的来源,我们看到该对话框是使用通过mContext.getThemeResId()获得的主题资源创建的,然后在ContextThemeWrapper中使用。

这可以大大帮助我们,因为我们所要做的就是覆盖Activity中的getThemeResId()方法(隐藏在公共API中),提供我们的自定义主题,子PreferenceScreen现在使用我们想要的任何自定义主题资源!

/**
 * 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;
}

请注意,由于此方法使用@hide进行注释,因此我们无法使用通常在此情况下使用的@Override注释;我们也无法调用super.getThemeResId()方法。如果你真的,真的希望能够有条件地覆盖它并调用超级实现作为后备,你将不得不使用Reflection来实现超级实现#s方法:

        try {
            ((Object) this).getClass().getMethod("getThemeResId").invoke(this);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

答案 3 :(得分:1)

正如所有其他答案尝试使用java代码解决它一样,这就是我完全使用xml并且没有声明我自己的首选项类的方法。

首先,我从 here 复制了首选项的完整布局,并将所有"@+android:id/xyz"更改为"@android:id/xyz"。然后在我的样式文件中,我将新样式声明为:

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

现在在AppTheme中,一个新的偏好条目:

<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>

现在,为这个新布局设置所需的所有样式。 就是这样。

答案 4 :(得分:0)

@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);
}