PreferenceActivity和主题不适用

时间:2010-04-11 00:05:40

标签: android themes android-preferences

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

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>

这是截图:

alt text http://i39.tinypic.com/16hnhh3.png

有任何解决方法吗?

5 个答案:

答案 0 :(得分: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>

除了应用程序本身,我没有必要将主题应用于任何内容。

答案 1 :(得分: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;
}

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

答案 2 :(得分: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);方法。通过这样做,它将产生如下所示的结果。

enter image description here

就是这样。

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

enter image description here

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

答案 3 :(得分:2)

答案 4 :(得分: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()方法。如果你真的,真的希望能够有条件地覆盖它并调用超级实现作为后备,你将不得不使用Reflection来获得超级实现的方法:

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