Домой Android разработкаUI и UX. Графика в Android Смена темы в Android приложении

Смена темы в Android приложении

by dilix
Смена тем в Android приложении

Темная тема в тренде. В приложениях под Android набирает популярность возможность переключения оформлений. Рассказываю как реализовать такой переключатель.

Есть как минимум два варианта реализации смены тем

  1. С пересозданием Activity/Fragment
  2. Без пересоздания Activity/Fragment

Смена темы с пересозданием Activity

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

Тут все просто, вы вызываете setTheme() и после этого recreate().

Важный момент, если вы хотите установить тему непосредственно в onCreate(), то делайте это перед вызовом super

@Override
protected void onCreate(Bundle savedInstanceState) {
    setTheme(myAwesomeTheme);
    super.onCreate(savedInstanceState);
    ...

Плюсы подхода

  • Минимальное вмешательство в код приложения
  • Гарантия консистентности внешнего вида

Минусы подхода

  • Пересоздание сложного UI может вызвать заметные лаги
  • Если есть элемент, который не восстанавливает свое состояние — будет выглядеть как баг

Смена темы без пересоздания Activity

Если вы хотите избавится от пересоздания UI, то придется поработать. Этот подход меняет общую тему приложения и в то же время уведомляет уже готовый интерфейс об изменениях в Runtime. Каждый элемент вашего экрана реагирует на изменение и перерисовывает себя.

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_toggle:
                if (mIsLightTheme) {
                    mIsLightTheme = false;
                    setTheme(R.style.AppThemeDark);
                    setSystemBarTheme(true);
                } else {
                    mIsLightTheme = true;
                    setTheme(R.style.AppThemeLight);
                    setSystemBarTheme(false);
                }
                break;
        }
        
        // уведомление о смене темы
        
        // Меняем "системный UI" прямо на месте
        TypedValue typedValue = new TypedValue();
        Resources.Theme theme = getTheme();

        theme.resolveAttribute(android.R.attr.windowBackground, typedValue, true);
        getWindow().getDecorView().setBackgroundColor(typedValue.data);

        theme.resolveAttribute(android.R.attr.colorPrimary, typedValue, true);
        getSupportActionBar().setBackgroundDrawable(new ColorDrawable(typedValue.data));

        theme.resolveAttribute(android.R.attr.colorPrimaryDark, typedValue, true);
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(typedValue.data);
        
        return super.onOptionsItemSelected(item);
    }

В GIF примере scrollview таким же образом переопределяет свой фон

...
TypedValue typedValue = new TypedValue();
Resources.Theme theme = getContext().getTheme();
theme.resolveAttribute(R.attr.bgChartColor, typedValue, true);
setBackgroundColor(typedValue.data);
...

А графики рисуются через onDraw(), Paint для который аналогично меняет цвет при общей смене стилей

theme.resolveAttribute(R.attr.axisChartColor, typedValue, true);
mAxisPaint = new Paint();
mAxisPaint.setColor(typedValue.data);

Плюсы подхода

  • Не тратится время на пересоздание элементов
  • Состояние UI будет консистентно (даже fling в scrollview на месте)

Минусы подхода

  • Нужно следить за каждым элементом и обрабатывать смену темы для него отдельно

Я верю, что смена темы это редкая операция. Принимая это во внимание, в большинстве случаев резонно пожертвовать минусами пересоздания Acitivity в пользу легкости реализации. И потратить сэкономленное время на устранение возможных проблем с производительностью или реализацию красивых переходов между экранами. Так и performance будет на высоте и общий look & feel приложения выиграет.

Хочешь обсудить Android разработку?
Заходи к нам Вконтакте, на Facebook и в Телеграм!

Добавить комментарий

Может быть интересно

Этот сайт использует Cookie файлы для улучшения вашего пользовательского взаимодействия. Используя данный сайт вы соглашается с этим. Принять Читать

Политика конфиденциальности и Cookies