在本教程中,我们将讨论并在应用程序中使用Android DayNight主题。如果你有一款带有阅读材料的应用程序,那么夜间模式对眼睛的舒缓很有帮助。
Android白夜主题
Android发布了一个新的主题:Theme.AppCompat.DayNight
,支持库为23.2.0
。多亏了这个主题,我们现在可以在应用程序的亮模式和暗模式之间切换。我们可以手动执行此操作,也可以让Android从您的手机中隐式检测当天的时间。这个主题通过用一个较暗的背景替换白色的闪光背景来增强应用程序在夜间的可读性和可用性。许多阅读器应用程序已经在其应用程序中部署了此主题。让我们通过创建一个包含空Activity的新Android Studio项目来开始我们的实现。
将主题添加到我们的style es.xml中
让我们将应用程序中的当前主题替换为DayNight主题。
1<style name="AppTheme" parent="Theme.AppCompat.DayNight">
2 <!-- Customize your theme here. -->
3 <item name="colorPrimary">@color/colorPrimary</item>
4 <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
5 <item name="colorAccent">@color/colorAccent</item>
6 </style>
要在我们的应用程序中设置DayNight主题,我们使用方法:AppCompatDelegate.setDefaultNightModel()
以下是上述方法中允许的参数。
MODE_NIGHT_YES
-手动开启夜间模式。MODE_NIGHT_NO
-手动关闭夜间模式。MODE_NIGHT_FOLLOW_SYSTEM
-使用系统设置来确定一天中的时间,并相应地切换夜间模式。这是默认参数。MODE_NIGHT_AUTO
-尝试从设备位置API自动检测时间。如果没有授予位置服务的运行时权限,则它使用系统时间。
在onCreate()
方法中添加以下代码。
1@Override
2 protected void onCreate(Bundle savedInstanceState) {
3 super.onCreate(savedInstanceState);
4 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); //For night mode theme
5 //AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); //For day mode theme
6 setContentView(R.layout.activity_main);
7 }
在调用setContent View
方法之前,应该始终设置主题。
什么是AppCompatDelegate?
AppCompatDelegate
是一个代表委托的类,可以用来将AppCompat的支持扩展到任何活动。让我们来看看我们的活动屏幕是什么样子,逐一启用白天模式和夜间模式。文本视图在夜间模式下将颜色更改为白色。这是因为TextView隐式包含名为
?Attr/ColorPrimary
的默认样式,该样式根据应用程序的亮/暗主题切换颜色。如果您在TextView上设置了自定义颜色@COLOR/RED
,它将不会在昼夜模式之间发生变化。日间模式下的工具栏文本颜色为黑色。如何在style es.xml
本身中设置为白色?
1<style name="AppTheme" parent="Theme.AppCompat.DayNight">
2 <!-- Customize your theme here. -->
3 <item name="colorPrimary">@color/colorPrimary</item>
4 <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
5 <item name="colorAccent">@color/colorAccent</item>
6 <item name="android:textColorPrimary">@android:color/white</item>
7 <item name="android:textColorSecondary">@android:color/white</item>
8 </style>
要检索当前夜间模式类型,我们使用方法AppCompatDelegate.getDefaultNightMode()
,该方法分别为前面讨论的每种类型返回一个整数。有了一个基本的想法后,我们来做一个应用程序,它将:
- 在白天/夜间模式下自定义资源、样式。
- 从用户界面切换白夜主题
- 查看各种UI小工具在夜间模式下的外观。
Android夜间模式项目结构
Android白夜主题示例代码
Activity_main.xml类文件的代码如下所示。
1<?xml version="1.0" encoding="utf-8"?>
2<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent">
5
6 <TextView
7 android:layout_width="wrap_content"
8 android:layout_height="wrap_content"
9 android:layout_alignParentTop="true"
10 android:layout_centerHorizontal="true"
11 android:layout_margin="@android:dimen/app_icon_size"
12 android:text="Welcome to this tutorial."
13 android:textColor="@color/daynight_textColor"
14 android:textSize="18sp" />
15
16 <ImageView
17 android:id="@+id/imageView"
18 android:layout_width="250dp"
19 android:layout_height="250dp"
20 android:layout_centerInParent="true"
21 android:src="@drawable/placeholder" />
22
23 <TextView
24 android:id="@+id/txtNightMode"
25 android:layout_width="wrap_content"
26 android:layout_height="wrap_content"
27 android:layout_alignBaseline="@+id/switchCompat"
28 android:layout_centerHorizontal="true"
29 android:paddingRight="8dp"
30 android:text="Night Mode"
31 android:textColor="@color/daynight_textColor" />
32
33 <android.support.v7.widget.SwitchCompat
34 android:id="@+id/switchCompat"
35 android:layout_width="wrap_content"
36 android:layout_height="wrap_content"
37 android:layout_alignParentBottom="true"
38 android:layout_marginBottom="@android:dimen/app_icon_size"
39 android:layout_toRightOf="@+id/txtNightMode"
40 android:checked="false"
41 android:textAppearance="?android:attr/textAppearanceMedium" />
42
43 <Button
44 android:id="@+id/button"
45 android:layout_width="wrap_content"
46 android:layout_height="wrap_content"
47 android:layout_above="@+id/imageView"
48 android:layout_alignLeft="@+id/txtNightMode"
49 android:layout_alignStart="@+id/txtNightMode"
50 android:text="CLICK ME"
51 android:textColor="@color/daynight_textColor" />
52</RelativeLayout>
- 我们在ImageView上设置了自定义文本颜色和可绘制。
- 要为白天和晚上的主题设置不同的颜色和可绘制内容,我们需要为资源创建单独的文件夹。
- 日期主题资源驻留在默认目录中。
- 夜间主题资源存放在名称后带有 -Night** 的文件夹中。
- 因此,我们在工程中创建了
values-night
和Drawable-night
文件夹。 - 对于要在日夜主题中切换的资源,两个目录中的可绘制文件名、颜色、样式名必须相同。
- 如果只在其中一个目录中定义了上述内容,则白天和夜晚主题中将使用相同的内容。
下面给出了VALUES和VALUES-NIGN文件夹中的style.xml代码。
1<resources>
2
3 <!-- Base application theme. -->
4 <style name="AppTheme" parent="Theme.AppCompat.DayNight">
5 <!-- Customize your theme here. -->
6 <item name="colorPrimary">@color/colorPrimary</item>
7 <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
8 <item name="colorAccent">@color/colorAccent</item>
9 <item name="android:textColorPrimary">@android:color/white</item>
10 </style>
11
12 <style name="MyDialog" parent="Theme.AppCompat.Light.Dialog.Alert"/>
13
14 <style name="MySwitch">
15 <item name="colorControlActivated">@color/switchColor</item>
16 </style>
17</resources>
1<resources>
2 <!-- Base application theme. values-night.xml -->
3 <style name="AppTheme" parent="Theme.AppCompat.DayNight">
4 <!-- Customize your theme here. -->
5 <item name="colorPrimary">@color/orange</item>
6 <item name="colorPrimaryDark">@color/orangeDark</item>
7 <item name="colorAccent">@color/colorAccent</item>
8 <item name="android:textColorPrimary">@android:color/white</item>
9 </style>
10
11 <style name="MyDialog" parent="Theme.AppCompat.DayNight.Dialog.Alert"/>
12
13 <style name="MySwitch">
14 <item name="colorControlActivated">@color/switchColor</item>
15 </style>
16</resources>
上面定义的样式用于设置定制标准的昼夜主题。Colors.xml各自的定义如下所示。[Caption id=)colors.xml=)colors.xml][Caption id=Attach_19360
Align=alignCenter
Width=434
]![安卓白天黑夜颜色白天标题]From Values文件夹[/Caption]MainActivity.java
类的代码如下所示。
1package com.journaldev.daynightmode;
2
3import android.content.Intent;
4import android.support.v7.app.AlertDialog;
5import android.support.v7.app.AppCompatActivity;
6import android.os.Bundle;
7import android.support.v7.app.AppCompatDelegate;
8import android.support.v7.widget.SwitchCompat;
9import android.view.View;
10import android.widget.Button;
11import android.widget.CompoundButton;
12
13public class MainActivity extends AppCompatActivity {
14
15 @Override
16 protected void onCreate(Bundle savedInstanceState) {
17 super.onCreate(savedInstanceState);
18 if (InitApplication.getInstance().isNightModeEnabled()) {
19 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
20 } else {
21 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
22 }
23 setContentView(R.layout.activity_main);
24
25 SwitchCompat switchCompat = findViewById(R.id.switchCompat);
26 Button button = findViewById(R.id.button);
27 button.setOnClickListener(new View.OnClickListener() {
28 @Override
29 public void onClick(View v) {
30 new AlertDialog.Builder(MainActivity.this, R.style.MyDialog)
31 .setTitle("Title")
32 .setMessage("Message")
33 .show();
34 }
35 });
36
37 if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES)
38 switchCompat.setChecked(true);
39
40 switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
41 @Override
42 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
43 if (isChecked) {
44 InitApplication.getInstance().setIsNightModeEnabled(true);
45 Intent intent = getIntent();
46 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
47 finish();
48 startActivity(intent);
49
50 } else {
51 InitApplication.getInstance().setIsNightModeEnabled(false);
52 Intent intent = getIntent();
53 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
54 finish();
55 startActivity(intent);
56 }
57
58 }
59 });
60
61 }
62}
在上面的代码中,我们使用开关在应用程序中的白天和夜间模式主题之间切换。我们将当前模式保存在SharedPreferences对象中。为什么? 一个活动的主题只能设置一次。因此,当切换开关时,我们需要将新模式保存在SharedPference对象中。我们使用Singleton Patternfor Application类。这样,可以在整个应用程序中使用相同的应用程序类实例。InitApplication.java
类的代码如下。
1package com.journaldev.daynightmode;
2
3import android.app.Application;
4import android.content.SharedPreferences;
5import android.preference.PreferenceManager;
6
7public class InitApplication extends Application {
8 public static final String NIGHT_MODE = "NIGHT_MODE";
9 private boolean isNightModeEnabled = false;
10
11 private static InitApplication singleton = null;
12
13 public static InitApplication getInstance() {
14
15 if(singleton == null)
16 {
17 singleton = new InitApplication();
18 }
19 return singleton;
20 }
21
22 @Override
23 public void onCreate() {
24 super.onCreate();
25 singleton = this;
26 SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
27 this.isNightModeEnabled = mPrefs.getBoolean(NIGHT_MODE, false);
28 }
29
30 public boolean isNightModeEnabled() {
31 return isNightModeEnabled;
32 }
33
34 public void setIsNightModeEnabled(boolean isNightModeEnabled) {
35 this.isNightModeEnabled = isNightModeEnabled;
36
37 SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
38 SharedPreferences.Editor editor = mPrefs.edit();
39 editor.putBoolean(NIGHT_MODE, isNightModeEnabled);
40 editor.apply();
41 }
42}
在这里,我们从共享首选项中更新和检索夜间模式类型。
Android夜间模式支持App输出
你可以从下面的链接下载最终的安卓白夜模式项目。