应用程式中夜间模式的Android DayNight主题
在本教程中,我们将在应用程序中讨论和使用Android DayNight主题。
如果您的应用程序带有阅读材料,那么夜间模式有助于缓解视线。
Android DayNight主题
Android发布了一个新主题:支持库" 23.2.0"的" Theme.AppCompat.DayNight"。
由于有了这个主题,我们现在可以在应用程序的亮模式和暗模式之间切换。
我们可以手动执行操作,也可以让Android通过您的手机隐式检测一天中的时间。
通过用较暗的背景替换白色的闪烁背景,该主题可在夜间提高应用程序的可读性和可用性。
许多阅读器应用程序已经在其应用程序中部署了此主题。
让我们从创建一个空活动的新Android Studio项目开始实施。
将主题添加到我们的styles.xml
让我们用DayNight one替换应用程序中的当前主题。
<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 -使用系统设置确定一天中的时间,并相应地切换NightMode。
这是默认参数。" 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?
" AppCompatDelegate"是一个类,代表一个委托,您可以用来将AppCompat的支持扩展到任何Activity。
让我们看看我们的活动屏幕在白天和夜晚模式下分别启用的样子。
TextView在夜间模式下将其颜色更改为白色。
这是因为TextView隐式包含名为?attr/colorPrimary的默认样式,该样式根据明暗应用主题切换颜色。
如果您在TextView上设置了自定义颜色" @ color/red",则在白天/夜晚模式之间不会更改。
白天模式下的工具列文字颜色为黑色。
如何在" styles.xml"本身中将其设置为白色?
<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()",该方法分别为前面讨论的每种类型返回一个整数。
有了一个基本的想法,我们来制作一个应用程序,它将:
在白天/夜晚模式下自定义资源,样式。
从UI切换DayNight主题
查看夜间模式下各种UI小部件的外观。
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主题中切换的资源的两个目录中的可绘制文件名,颜色,样式名称必须相同。
如果以上内容仅在一个目录中定义,则白天和黑夜主题中都将使用相同的内容。
值和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>
上面定义的样式用于设置自定义标准DayNight主题。
如下所示定义了colors.xml的相应内容。
values-night文件夹中的colors.xml
来自values文件夹的colors.xml
下面给出了MainActivity.java类的代码。
package com.theitroad.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);
}
}
});
}
}
在上面的代码中,我们使用Switch在应用程序中的白天和夜晚模式主题之间进行切换。
我们将当前模式保存在SharedPreferences对象中。
为什么?
活动的主题只能设置一次。
因此,当切换开关时,我们需要将新模式保存在SharedPreference对象中。
我们将Singleton Pattern用于Application类。
这样,可以在整个应用程序中使用Application类的相同实例。
下面给出了InitApplication.java类的代码。
package com.theitroad.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();
}
}
其中我们可以从"共享首选项"中更新和检索夜间模式类型。

