Android app的暗黑模式适配实现
原文地址: Android app的暗黑模式适配实现 - Stars-One的杂货小窝
很久之前放在草稿箱的一篇简单笔记,是之前蓝奏云批量下载工具Android版本实现暗黑主题的适配记录
本文所说的这里的暗黑主题,应该只支持Android10系统,不过我手头的Flyme系统(Android9)上测试也有效果,其他低版本则没有测试(不过之后版本也没用户反馈过此问题应该视作都兼容了吧...)
效果的话,没有搞太复杂,APP的主题会自动随着系统主题变化(没搞那种APP内部切换主题)
写的比较简陋,各位见笑了 😃
效果
原理说明
Android10开始,支持深色主题,我们想要实现,就是在values
和values-night
下写2个themes.xml
,里面使用不同的主题色即可
由于APP开发时间比较久,如果想要适配深色主题,要改的地方可太多了
于是我这里就是选择了亮色和暗色都设置一套APP的文本颜色和背景颜色,之后即可对全局APP的文字和组件背景色进行覆盖,从而一键式完成暗黑模式的适配工作
颜色文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#03A9F4</color>
<color name="colorPrimaryDark">#0288D1</color>
<color name="colorAccent">#40C4FF</color>
<color name="colorGrey">#9e9e9e</color>
<color name="colorBlack">#000000</color>
<color name="colorBackground">#f1f1f1</color>
<color name="color_rose">#dd1c73</color>
</resources>
亮色主题:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<!--用作背景色 -->
<item name="colorOnPrimary">@color/white</item>
<!-- 第二背景色,与上面的反过来 -->
<item name="colorOnSecondary">@color/gray_600</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColor">@color/black</item>
<item name="backgroundColor">@color/colorPrimary</item>
<item name="android:statusBarColor">?attr/colorPrimary</item>
</style>
暗色主题:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimaryDark</item>
<item name="colorPrimaryDark">@color/colorPrimary</item>
<!--用作背景色 -->
<item name="colorOnPrimary">@color/black</item>
<item name="colorOnSecondary">@color/white</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColor">@color/white20</item>
<item name="backgroundColor">@color/colorPrimaryDark</item>
<item name="android:statusBarColor">?attr/colorPrimary</item>
</style>
上文提到的3个属性即是覆盖了系统的文本颜色和背景颜色,因为APP是沉浸式状态栏设计,所以我状态栏的颜色也一起设置了
<item name="android:textColor">@color/white20</item>
<item name="backgroundColor">@color/colorPrimaryDark</item>
<item name="android:statusBarColor">?attr/colorPrimary</item>
PS:上述我设置的暗色主题的字体颜色是有点灰色white20
,各位可以看着调整下
官方的推荐是使用下面4个属性:
?attr/colorControlNormal
一种通用图标颜色。该颜色包含一个停用状态?android:attr/textColorPrimary
: 这是一种通用型文本颜色。它在浅色主题背景下接近于黑色,在深色主题背景下接近于白色。该颜色包含一个停用状态。?attr/colorSurface
:它代表表面的颜色,通常是应用程序的主要背景色或容器的背景色。在浅色主题中,通常为白色或浅灰色,在深色主题中,通常为黑色或深灰色。?attr/colorOnSurface
:属性用于设置界面元素的前景颜色,如文本、图标等。它代表了在 colorSurface 背景上显示的颜色。在浅色主题中,通常为深色(如黑色)以提供对比度,在深色主题中,通常为浅色(如白色)。
如果是在刚开始写一个新的APP,注意使用上述颜色,之后就比较好的可以支持暗黑模式了,如下面代码
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始说明"
android:textColor="?android:attr/textColorPrimary"
android:textSize="18sp"
android:textStyle="bold" />
其他补充
1.Toolbar颜色变黑色
这里发现设置的Toolbar在暗黑模式下是变为了黑色,但是我不想要黑色,想要我自己设置的暗一点蓝色效果,于是使用了MaterialToolbar
,并对其进行了属性的设置就可达到需要的效果
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:navigationIconTint="?attr/colorOnPrimary"
app:popupTheme="@style/AppTheme"
app:theme="@style/AppTheme"
app:titleTextColor="?attr/colorOnPrimary"
app:title="@string/app_name"/>
background
背景色navigationIconTint
左侧导航图标(返回箭头)的图标颜色titleTextColor
Toolbar的标题颜色
2.获取颜色代码方法
想要在代码里获取?android:attr/textColorPrimary
这个颜色,如何获取?
@ColorInt
fun Context.getColorResCompat(@AttrRes id: Int): Int {
val resolvedAttr = TypedValue()
this.theme.resolveAttribute(id, resolvedAttr, true)
val colorRes = resolvedAttr.run { if (resourceId != 0) resourceId else data }
return ContextCompat.getColor(this, colorRes)
}
使用:
val color = getColorResCompat(android.R.attr.textColorPrimary)
textview.setTextColor(color)