25

大家好,我在清单文件中设置了这样的主题:

android:theme="@android:style/Theme.Light"

但是我在首选项活动中有一个问题,在主首选项中主题显示正常,但是如果我进入子首选项,主题会变得混乱,它不是应有的白色,全黑,字体是黑色,所以你看不到太多,当我开始点击任何项目时,它们有时会变白,但很快就会恢复为黑色。这只发生在 2.1 上,在真实设备和模拟器中。在运行 1.6 的模拟器上测试,它工作正常。以下是首选项 xml 文件的部分代码:

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

这是一个屏幕截图:

替代文字

任何解决方法?

4

5 回答 5

15

有人刚刚在http://code.google.com/p/android/issues/detail?id=4611发布了一个解决方法

简而言之,顶级首选项屏幕似乎可以识别主题,但嵌套的却不能。因此,解决方法建议为嵌套的 PreferenceScreen 创建顶级 PreferenceActivity,然后通过 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>

除了应用程序本身,我不必将主题应用于任何东西。

于 2011-04-24T18:40:58.210 回答
4

您还可以使用此技术来覆盖内部首选项屏幕的样式:

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

此代码将主首选项屏幕的样式应用于单击的首选项屏幕。

于 2013-04-17T17:28:23.397 回答
3

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

要更改主题,只需这样做:

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

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

在此处输入图像描述

就这样。

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

在此处输入图像描述

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

于 2013-03-27T11:11:34.590 回答
2

这似乎是一个错误。请参阅http://code.google.com/p/android/issues/detail?id=4611

于 2010-11-01T21:42:13.617 回答
0

有一个更简单的解决方案,如果你可以使用看起来像黑魔法的东西来完成这个......

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

这可以极大地帮助我们,因为在Context中使用的PreferenceScreen实际上是我们的PreferenceActivity,所以我们所要做的就是重写getThemeResId()方法(对公共 API 隐藏),以提供我们的自定义主题,并且子 PreferenceScreen 现在使用任何我们想要的自定义主题资源!

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

请注意,由于此方法使用 注释@hide,因此我们不能使用@Override通常在这种情况下使用的注释;而且我们也不能调用该super.getThemeResId()方法。如果您真的非常希望能够有条件地覆盖它并调用超级实现作为后备,您将不得不使用反射来获取超级实现的方法:

        try {
            ((Object) this).getClass().getMethod("getThemeResId").invoke(this);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
于 2014-09-01T21:39:52.070 回答