Подтвердить что ты не робот

Реализация пользовательского выбора темы

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

Я думал о создании другого макета для каждой темы, а в onCreate просто был переключатель для метода setContentView(). Сначала я загрузил сохраненное значение SharedPreference (целое число) и в зависимости от того, какое это значение отображает соответствующий макет. Очевидно, пользователь может изменить значение SharedPreference кнопкой или чем-то.

Поскольку эти макеты будут в основном одинаковыми, но с разными цветами, я бы хотел использовать те же идентификаторы для моих TextViews и других представлений в каждом файле макета. Мой главный вопрос: это вызовет проблемы?

Извините за стену текста без кода. Я просто хотел бы получить общее представление о хорошей практике для этой ситуации. Спасибо заранее.

4b9b3361

Ответ 1

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

Как уже указывалось - создайте несколько тем Android, используя это руководство. В вашем файле styles.xml будет как минимум два элемента <style>. Например:

<style name="Theme.App.Light" parent="@style/Theme.Light">...</style>
<style name="Theme.App.Dark" parent="@style/Theme">...</style>

Теперь вы должны применить один из этих стилей к своей деятельности. Я делаю это в методе activitie onCreate перед любым другим вызовом:

setTheme(MyApplication.getThemeId());

getThemeId - это метод, который возвращает кэшированный идентификатор темы:

public static int getThemeId()
{
    return themeId;
}

Это поле обновляется другим способом:

public static void reloadTheme()
{
    themeSetting = PreferenceManager.getDefaultSharedPreferences(context).getString("defaultTheme", "0");
    if(themeSetting.equals("0"))
        themeId = R.style.Theme_Light;
    else
        themeId = R.style.Theme_Dark;
}

Который вызывается при изменении настроек (и, конечно, при запуске). Эти два метода находятся в классе MyApplication, который расширяет Application. Слушатель изменения предпочтений описан в конце этого поста и находится в основном классе деятельности.

Последнее и довольно важное - тема применяется, когда начинается действие. Предполагая, что вы можете изменить тему только на экране настроек и что есть только один способ попасть туда, то есть только из одного (основного) действия, это действие не будет перезапущено, когда вы выйдете из экрана настроек - старая тема все еще будет используемый. Вот исправление для этого (возобновление вашей основной деятельности):

@Override
protected void onResume() {
    super.onResume();
    if(schduledRestart)
    {
        schduledRestart = false;
        Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(i);
    }
}

scheduledRestart - логическая переменная, изначально установленная в false. Значение true, когда тема изменяется этим слушателем, который также обновляет кэшированный идентификатор темы, упомянутый ранее:

private class ThemeListener implements OnSharedPreferenceChangeListener{

    @Override
    public void onSharedPreferenceChanged(SharedPreferences spref, String key) {
        if(key.equals("defaultTheme") && !spref.getString(key, "0").equals(MyApplication.getThemeSetting()))
        {
            MyApplication.reloadTheme();
            schduledRestart = true;
        }
    }


sp = PreferenceManager.getDefaultSharedPreferences(this);

listener = new ThemeListener();
sp.registerOnSharedPreferenceChangeListener(listener);

Не забудьте сохранить ссылку на объект слушателя, иначе он будет собран мусором (и перестанет работать).

Ответ 2

Вы также можете изменить динамическую тему, используя:

ContextThemeWrapper w = new ContextThemeWrapper(this, <newTHEMEId>);
getTheme().setTo(w.getTheme());

Перед onCreate для каждого действия.

Ответ 3

Он работает, если вы делаете это так, и я не думаю, что это вызовет какие-либо проблемы, но это похоже на много хлопот (вам нужно умножить все свои макеты на все темы, которые вы хотите добавить. Если позже вы захотите изменить ресурс в макете, вам придется изменить его во всех темах. Вы обязательно должны его забыть)

Почему бы не использовать функцию Стили и темы для Android?

Их можно легко применить ко всей деятельности:

<activity android:theme="@style/my_theme">

Таким образом, когда вы обнаруживаете изменение в значении SharedPreferences, которое вы используете (кнопка в активности предпочтений или что-то еще), вы можете просто переключить стиль. Или лучше, вы можете установить стиль для чтения вашего значения предпочтений во время выполнения (при создании активности) и соответствующим образом применить соответствующий стиль/тему.