PreferenceActivity и тема не применяются - PullRequest
25 голосов
/ 11 апреля 2010

Привет всем, я установил тему в файле манифеста следующим образом:

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>

А вот скриншот:

альтернативный текст http://i39.tinypic.com/16hnhh3.png

Есть ли обходные пути?

Ответы [ 5 ]

15 голосов
/ 24 апреля 2011

Кто-то только что опубликовал решение в http://code.google.com/p/android/issues/detail?id=4611

Короче говоря, экраны предпочтений верхнего уровня распознают тему, а вложенные - нет. Поэтому в качестве обходного пути рекомендуется создать PreferenceActivity верхнего уровня для вложенного PreferenceScreen, а затем вызвать это новое действие через намерение:

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

Мне не нужно было применять тему ни к чему, кроме самого приложения.

4 голосов
/ 17 апреля 2013

Вы также можете использовать эту технику для переопределения стилей экранов внутренних настроек:

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

Этот код применяет стиль основного экрана настроек к экрану предпочтений, по которому щелкают.

3 голосов
/ 27 марта 2013

Наконец-то я узнал, как программно изменить тему "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, вы должны сделать еще один PreferenceActivity для этого вложенного PreferenceScreen и вызвать там метод setTheme(R.style.yourtheme);.

2 голосов
/ 02 ноября 2010

Это похоже на ошибку. Смотри http://code.google.com/p/android/issues/detail?id=4611

0 голосов
/ 02 сентября 2014

Существует еще более простое решение, если вы в порядке, используя черную магию для достижения этой цели ...

Глядя на источник 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();
        }
...