Android app的暗黑模式適配實現

原文地址: Android app的暗黑模式適配實現 - Stars-One的雜貨小窩

很久之前放在草稿箱的一篇簡單筆記,是之前藍奏雲批量下載工具Android版本實現暗黑主題的適配記錄

本文所說的這裏的暗黑主題,應該只支持Android10系統,不過我手頭的Flyme系統(Android9)上測試也有效果,其他低版本則沒有測試(不過之後版本也沒用戶反饋過此問題應該視作都兼容了吧...)

效果的話,沒有搞太複雜,APP的主題會自動隨着系統主題變化(沒搞那種APP內部切換主題)

寫的比較簡陋,各位見笑了 😃

效果

原理說明

Android10開始,支持深色主題,我們想要實現,就是在valuesvalues-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)

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章