Ответ 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);
Не забудьте сохранить ссылку на объект слушателя, иначе он будет собран мусором (и перестанет работать).