アプリ内のナイトモード用のAndroid DayNightテーマ
このチュートリアルでは、Androidのデイナイトテーマについて説明し、アプリケーションで使用します。もし読み物のあるアプリを持っているなら、ナイトモードは目の疲れを軽減するために役立ちます。
アンドロイドの日夜テーマ
Androidは新しいテーマ、Theme.AppCompat.DayNightとサポートライブラリ23.2.0をリリースしました。このテーマのおかげで、アプリケーションの明るいモードと暗いモードを切り替えることができます。手動で切り替えることも、Androidがお使いの携帯電話の時間から自動的に切り替えることもできます。このテーマにより、夜間のアプリケーションで蛍光白い背景をより暗いものに置き換えることで、読みやすさと使いやすさが向上します。すでに多くのリーダーアプリケーションがこのテーマを活用しています。空のアクティビティで新しいAndroid Studioプロジェクトを作成して実装を始めましょう。
themes.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 – Enables night mode manually.
- MODE_NIGHT_NO – Disables night mode manually.
- MODE_NIGHT_FOLLOW_SYSTEM – Uses the system settings to determine the time of day and toggles NightMode accordingly. This is the default argument.
- MODE_NIGHT_AUTO – This tries to auto-detect the time from the device location APIs. If the runtime permission for location services isn’t granted, then it uses the system time.
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() メソッドを使用します。このメソッドは、先ほど説明した各タイプに対して整数を返します。基本的なアイデアを得たら、次はアプリケーションを作成しましょう。
- Customise resources, styles in day/night modes.
- Toggle DayNight theme from the UI
- See how various UI widgets look in Night Mode.
アンドロイドのナイトモードプロジェクトの構造
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>
- We’ve set a custom text color and drawable on the ImageView.
- To set different colors and drawables for day and night themes, we need to create separate folders for the resources.
- The day theme resources reside in the default directory.
- The night theme resources reside in folders with names appended with -night.
- Hence we’ve created values-night and drawable-night folders in our project.
- The drawable filename, colors, style names must be the same in both the directories for the resources you wish to toggle in DayNight theme.
- If the above things are defined in only one of the directories, the same would be used in day and night themes.
values フォルダと values-night フォルダ内の styles.xml に記載されているコードは以下の通りです。
<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.scdev.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);
}
}
});
}
}
上記のコードでは、アプリケーション内で昼夜モードのテーマを切り替えるためにスイッチを使用します。現在のモードはSharedPreferencesオブジェクトに保存します。なぜなら、アクティビティのテーマは一度しか設定できないためです。したがって、スイッチが切り替わると、新しいモードをSharedPreferencesオブジェクトに保存する必要があります。ApplicationクラスではSingletonパターンを使用しています。これにより、同じApplicationクラスのインスタンスをアプリケーション全体で使用できます。InitApplication.javaクラスのコードは以下の通りです。
package com.scdev.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のナイトモード対応アプリ出力
AndroidのDayNightテーマの例プロジェクトのダウンロード