如何在Android中实现黑暗模式

182 阅读5分钟

如何在Android中实施黑暗模式

在最近,关于黑暗模式有很多人在兴奋。用户只需点击一个按钮就可以改变其应用程序的整个外观和感觉。众多开发者和谷歌、Facebook和Twitter等大公司已经在其应用程序中实施了这一功能。

简介

黑暗模式功能不需要任何重要的解释。你很可能已经在你的手机或电脑上使用过黑暗模式。因此,我们可以简单地将黑暗模式定义为将你的应用程序的整体颜色变为黑色的一种设置。移动和网络应用都支持暗色模式。

Google Play商店中的许多应用程序已经配备了这一功能。甚至有传言说,启用黑暗模式有助于延长电池寿命。此外,它还能提高应用程序的视觉吸引力,特别是对那些有眼睛问题的用户。

目标

使用Kotlin将黑暗模式功能融入到一个Android应用程序中。

前提条件

本教程适合于中级学习者。因此,你必须熟悉Kotlin编程语言,以及Android studio的文件或项目结构。

说到程序,你将需要在电脑上安装Android Studio。还建议拥有一个实体的Android设备。这是因为我们将在手机上测试该应用程序。

创建项目

打开Android Studio并创建一个新项目。你可以给它起任何名字。在我的例子中,该项目被称为darkmode 。然后,选择一个空的活动,进入下一个屏幕。

在这个窗口中,确保你将最低SDK设置为API 21或Lollipop。然后你可以点击完成,等待项目的设置。这通常需要几分钟时间,取决于你的互联网连接。注意:在本教程中,我们不需要安装任何其他的依赖性。

创建attrs.xml文件

我们需要在一个attrs.xml 文件中声明我们的颜色属性。我们以后将从这个文件而不是默认的colors.xml 中访问我们的设置。在res/values 文件夹中,创建一个新的资源文件并命名为attrs.xml 。在这个文件中添加以下代码。

<resources>
    <declare-styleable name="ds">
       <attr name="background_color" format="color"/>
        <attr name="text_color" format="color"/>
        <attr name="button_color" format="color"/>
    </declare-styleable>
</resources>

在这里<declare-styleable name="ds"></declare-styleable> ,允许我们添加我们应用程序的样式属性。如代码片段所示,该应用程序将有诸如background_color,text_color, 和button_color 等元素。确保所有这些属性都有color 的格式。

修改style.xml文件

我们需要在styles.xml 中添加我们的光明和黑暗主题。

当你打开这个文件时,你会发现有一个预先存在的名为AppTheme 的样式。这将作为我们的浅色主题。然后我们在AppTheme 下面添加黑暗主题样式。下一步是将attrs.xml 文件中的元素纳入两个主题中。如下图所示。

<resources>
    <!-- Light application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="background_color">#ffff</item>
   <!--        Our app's background colour when light mode is on == white-->
        <item name="text_color">#000</item>
   <!--        Text color is black-->
        <item name="button_color">@color/colorAccent</item>
    </style>

    <!-- dark application theme. -->
    <style name="darkTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">#000</item>
        <item name="colorPrimaryDark">#000</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="background_color">#131313</item>
<!--     Our app's background changes to black when dark mode is activated -->
        <item name="text_color">#ffff</item>
<!--     text and button color change to white to contrast with the app's background-->
        <item name="button_color">#ffff</item>
    </style>

</resources>

请注意,深色主题应该已经有浅色主题中描述的所有元素,但颜色不同。

创建用户界面

在本教程中,我们的应用程序将有一个简单的用户界面。该用户界面将包括一个开关和一个文本视图。为了开始,打开activity_main.xml 。将布局从ConstraintLayout 改为LinearLayout

记住要把orientation 设置为垂直。接下来,添加一个Switch和TextView widgets,并将它们放置在页面的中心位置。最后,为Switch小部件添加一个ID。

下面是activity_main.xml 的完整代码。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="?attr/background_color"
    android:padding="10dp"
    tools:context=".MainActivity">

    <TextView   // textview widget
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English."
        android:layout_gravity="center"
        android:layout_marginTop="80dp"
        android:padding="10dp"
        android:textColor="?attr/text_color"
        android:textAlignment="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Switch
        android:id="@+id/switchtheme" // Add switch id
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="80dp"
        android:textColor="?attr/text_color"
        android:text="Switch Theme"/>

</LinearLayout>

记住要设置UI组件的颜色。如前所述,我们将通过我们先前创建的attrs.xml 文件来访问我们的颜色。因此,我们使用"?attr/text_color" 来为我们的小部件设置颜色。如果你忽略了这个关键的方面,你的应用程序将无法工作。

检查状态和处理点击事件

每当我们的应用程序启动时,我们需要检查哪个主题是默认启用的。我们通过使用AppCompatDelegate 类来做到这一点。下面是检查应用程序主题的代码片段。

if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) {
    setTheme(R.style.darkTheme) //when dark mode is enabled, we use the dark theme
} else {
    setTheme(R.style.AppTheme)  //default app theme
}

请注意,你应该在onCreate 函数之后或在 activity_main.xml 布局被初始化之前立即包含上面的代码片段。

接下来,我们需要处理我们的开关的点击事件。记住,我们已经给这个组件分配了switchtheme 。因此,我们使用这个ID来监听变化,如下所示。

switchtheme.setOnCheckedChangeListener { _, isChecked ->
    if (isChecked) {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
    } else {
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
    }

}

isChecked 是一个布尔变量。当isChecked 为真时,这意味着我们需要启用黑暗主题。这可以通过下面的代码段来完成。

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)

我们设置默认的浅色主题,如下图所示。

AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)

下面是MainActivity.kt 的代码。

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.CompoundButton
import androidx.appcompat.app.AppCompatDelegate
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) {
            setTheme(R.style.darkTheme)
        } else {
            setTheme(R.style.AppTheme)
        }
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        switchtheme.setOnCheckedChangeListener { _, isChecked ->
            if (isChecked) {
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
            } else {
                AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
            }

        }
    }
}

如果你正确地遵循了上述步骤,你的应用程序现在应该有一个黑暗模式。下面的gif图显示了黑暗模式的运行情况。

demo.

结论

在我们的移动应用程序中实现黑暗模式的确是一件有趣的事情。我希望这个教程能让你掌握所需的技能和知识,以便在黑暗主题上工作。如果你有什么不明白的地方,可以随时重温上述步骤。