Как переключать темы (ночной режим) без перезапуска?
Я создал несколько приложений, поддерживающих несколько тем, но мне всегда приходилось перезапускать приложение, когда пользователь переключает тему, потому что setTheme()
нужно вызывать до setContentView()
.
Я был в порядке, пока не нашел это приложение. Он может легко переключаться между двумя темами, а также с переходами/анимациями!
![enter image description here]()
Пожалуйста, дайте мне несколько советов о том, как это было реализовано (и анимации тоже). Спасибо!
Ответы
Ответ 1
@Александр Хансен отвечает в основном ответил на это...
Не знаю, почему это не было принято... Возможно, из-за финиша()/startActivity().
Я проголосовал за это, и я попытался прокомментировать, но не могу...
В любом случае, я бы сделал именно то, что он описал в терминах стилей.
<style name="AppThemeLight" parent="Theme.AppCompat.Light">
<!-- Customize your theme here. -->
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
<!-- Customize your theme here. -->
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<!-- This will set the fade in animation on all your activities by default -->
<style name="WindowAnimationTransition">
<item name="android:windowEnterAnimation">@android:anim/fade_in</item>
<item name="android:windowExitAnimation">@android:anim/fade_out</item>
</style>
Но вместо того, чтобы закончить/начать с нового намерения:
Intent intent = new Intent(this, <yourclass>.class);
startActivity(intent);
finish();
Я бы сделал:
@Override
protected void onCreate(Bundle savedInstanceState) {
// MUST do this before super call or setContentView(...)
// pick which theme DAY or NIGHT from settings
setTheme(someSettings.get(PREFFERED_THEME) ? R.style.AppThemeLight : R.style.AppThemeDark);
super.onCreate(savedInstanceState);
}
// Somewhere in your activity where the button switches the theme
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// decide which theme to use DAY or NIGHT and save it
someSettings.save(PREFFERED_THEME, isDay());
Activity.this.recreate();
}
});
Эффект показан на видеоролике...
Ответ 2
Переход/анимация автоматически изменяет тему при перезапуске активности, и это можно сделать, добавив в ваши темы элементы "android: windowanimationStyle", а затем ссылаясь на стиль, в котором вы указываете, как действие должно анимироваться, когда он входит и выходит.
Обратите внимание, что это делает анимацию применимой ко всем действиям с этой темой.
<style name="AppThemeLight" parent="Theme.AppCompat.Light">
<!-- Customize your theme here. -->
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
<!-- Customize your theme here. -->
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
</style>
<!-- This will set the fade in animation on all your activities by default -->
<style name="WindowAnimationTransition">
<item name="android:windowEnterAnimation">@android:anim/fade_in</item>
<item name="android:windowExitAnimation">@android:anim/fade_out</item>
</style>
Затем, когда вы хотите изменить тему, вы можете сделать это, нажав кнопку:
AppSettings settings = AppSettings.getInstance(this);
settings.set(AppSettings.Key.USE_DARK_THEME,
!settings.getBoolean(AppSettings.Key.USE_DARK_THEME));
Intent intent = new Intent(this, <yourclass>.class);
startActivity(intent);
finish();
Затем в вашем методе onCreate
используйте setTheme()
, чтобы применить тему, которая в настоящее время установлена в AppSettings следующим образом:
AppSettings settings = AppSettings.getInstance(this);
setTheme(settings.getBoolean(AppSettings.Key.USE_DARK_THEME) ? R.style.AppThemeDark : R.style.AppThemeLight);
super.onCreate(savedInstanceState);
setContentView(<yourlayouthere>);
Отметьте этот смысл для справки: https://gist.github.com/alphamu/f2469c28e17b24114fe5
Ответ 3
Нет ничего, что помешает вам снова вызвать setTheme()
, а затем setContentView()
. Вам просто нужно немного изменить структуру приложения, чтобы при изменении темы вам нужно было повторно инициализировать любые переменные-члены, которые могут содержать ссылки на объекты View
.