应用程式中夜间模式的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(); } }
其中我们可以从"共享首选项"中更新和检索夜间模式类型。