Поиск по сайту:

Android DayNight Theme для ночного режима в приложении


В этом уроке мы обсудим тему Android DayNight и используем ее в нашем приложении. Если у вас есть приложение с материалами для чтения, то наличие ночного режима полезно для глаз.

Тема дня и ночи для Android

Android выпустила новую тему: Theme.AppCompat.DayNight с библиотекой поддержки 23.2.0. Благодаря этой теме мы теперь можем переключаться между светлым и темным режимами нашего приложения. Мы можем сделать это вручную или позволить Android автоматически определять время суток с вашего телефона. Эта тема повышает читабельность и удобство использования вашего приложения в ночное время, заменяя яркий белый фон более темным. Многие приложения для чтения уже развернули эту тему в своих приложениях. Давайте начнем с нашей реализации, создав новый проект Android Studio с пустой активностью.

Добавляем тему в наш styles.xml

Заменим текущую тему в нашем приложении на DayNight.

<style name="AppTheme" parent="Theme.AppCompat.DayNight">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

Чтобы установить тему DayNight в нашем приложении, мы используем метод: AppCompatDelegate.setDefaultNightMode() Ниже приведены аргументы, разрешенные в приведенном выше методе.

  • MODE_NIGHT_YES – включает ночной режим вручную.
  • MODE_NIGHT_NO – вручную отключает ночной режим.
  • MODE_NIGHT_FOLLOW_SYSTEM — использует системные настройки для определения времени суток и соответствующим образом переключает ночной режим. Это аргумент по умолчанию.
  • MODE_NIGHT_AUTO — пытается автоматически определить время с помощью API определения местоположения устройства. Если разрешение времени выполнения для служб определения местоположения не предоставлено, используется системное время.

Добавьте следующий код в метод onCreate().

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); //For night mode theme
        //AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); //For day mode theme
        setContentView(R.layout.activity_main);
    }

Тема всегда должна быть установлена до вызова метода setContentView.

Что такое AppCompatDelegate?

<style name="AppTheme" parent="Theme.AppCompat.DayNight">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:textColorPrimary">@android:color/white</item>
        <item name="android:textColorSecondary">@android:color/white</item>
    </style>

Чтобы получить текущий тип ночного режима, мы используем метод AppCompatDelegate.getDefaultNightMode(), который возвращает целое число для каждого из рассмотренных ранее типов соответственно. Имея базовую идею, давайте сделаем приложение, которое будет:

  • Настройка ресурсов, стилей в дневном/ночном режимах.
  • Переключить тему DayNight из пользовательского интерфейса
  • Посмотрите, как различные виджеты пользовательского интерфейса выглядят в ночном режиме.

Структура проекта ночного режима Android

Пример кода темы Android DayNight

Код для файла класса activity_main.xml приведен ниже.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_margin="@android:dimen/app_icon_size"
        android:text="Welcome to this tutorial."
        android:textColor="@color/daynight_textColor"
        android:textSize="18sp" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:layout_centerInParent="true"
        android:src="@drawable/placeholder" />


    <TextView
        android:id="@+id/txtNightMode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/switchCompat"
        android:layout_centerHorizontal="true"
        android:paddingRight="8dp"
        android:text="Night Mode"
        android:textColor="@color/daynight_textColor" />


    <android.support.v7.widget.SwitchCompat
        android:id="@+id/switchCompat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="@android:dimen/app_icon_size"
        android:layout_toRightOf="@+id/txtNightMode"
        android:checked="false"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/imageView"
        android:layout_alignLeft="@+id/txtNightMode"
        android:layout_alignStart="@+id/txtNightMode"
        android:text="CLICK ME"
        android:textColor="@color/daynight_textColor" />
</RelativeLayout>

  • Мы установили пользовательский цвет текста и возможность его рисования в ImageView.
  • Чтобы установить разные цвета и рисунки для дневной и ночной тем, нам нужно создать отдельные папки для ресурсов.
  • Ресурсы дневной темы находятся в каталоге по умолчанию.
  • Ресурсы ночной темы находятся в папках, имена которых заканчиваются с -night.
  • Поэтому мы создали папки values-night и drawable-night в нашем проекте.
  • Доступное имя файла, цвета и имена стилей должны быть одинаковыми в обоих каталогах для ресурсов, которые вы хотите переключать в теме DayNight.
  • Если вышеуказанные вещи определены только в одном из каталогов, то же самое будет использоваться в дневной и ночной темах.

Ниже приведен код стилей.xml в папках values и values-night.

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.DayNight">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:textColorPrimary">@android:color/white</item>
    </style>

    <style name="MyDialog" parent="Theme.AppCompat.Light.Dialog.Alert"/>

    <style name="MySwitch">
        <item name="colorControlActivated">@color/switchColor</item>
    </style>
</resources>
<resources>
    <!-- Base application theme. values-night.xml -->
    <style name="AppTheme" parent="Theme.AppCompat.DayNight">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/orange</item>
        <item name="colorPrimaryDark">@color/orangeDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:textColorPrimary">@android:color/white</item>
    </style>

    <style name="MyDialog" parent="Theme.AppCompat.DayNight.Dialog.Alert"/>

    <style name="MySwitch">
        <item name="colorControlActivated">@color/switchColor</item>
    </style>
</resources>
package com.journaldev.daynightmode;

import android.content.Intent;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.SwitchCompat;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (InitApplication.getInstance().isNightModeEnabled()) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
        } else {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
        }
        setContentView(R.layout.activity_main);


        SwitchCompat switchCompat = findViewById(R.id.switchCompat);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new AlertDialog.Builder(MainActivity.this, R.style.MyDialog)
                        .setTitle("Title")
                        .setMessage("Message")
                        .show();
            }
        });

        if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES)
            switchCompat.setChecked(true);

        switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    InitApplication.getInstance().setIsNightModeEnabled(true);
                    Intent intent = getIntent();
                    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                    finish();
                    startActivity(intent);

                } else {
                    InitApplication.getInstance().setIsNightModeEnabled(false);
                    Intent intent = getIntent();
                    intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                    finish();
                    startActivity(intent);
                }


            }
        });

    }
}

В приведенном выше коде мы используем переключатель для переключения между темами дневного и ночного режимов в нашем приложении. Мы сохраняем текущий режим в классе Singleton Pattern for Application. Таким образом, один и тот же экземпляр класса Application может использоваться во всем приложении. Код для класса InitApplication.java приведен ниже.

package com.journaldev.daynightmode;

import android.app.Application;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;


public class InitApplication extends Application {
    public static final String NIGHT_MODE = "NIGHT_MODE";
    private boolean isNightModeEnabled = false;

    private static InitApplication singleton = null;

    public static InitApplication getInstance() {

        if(singleton == null)
        {
            singleton = new InitApplication();
        }
        return singleton;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        singleton = this;
        SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        this.isNightModeEnabled = mPrefs.getBoolean(NIGHT_MODE, false);
    }

    public boolean isNightModeEnabled() {
        return isNightModeEnabled;
    }

    public void setIsNightModeEnabled(boolean isNightModeEnabled) {
        this.isNightModeEnabled = isNightModeEnabled;

        SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = mPrefs.edit();
        editor.putBoolean(NIGHT_MODE, isNightModeEnabled);
        editor.apply();
    }
}

Именно здесь мы обновляем и получаем тип ночного режима из общих настроек.

Вывод приложения поддержки ночного режима Android

Скачать пример проекта темы DayNight для Android