【首發】根據桌布修改App主題,它真的來了
1、前言
曾經產品經理的奇思妙想,現在終於可以實現了...
2、效果
效果中,原本是紅色桌布對應的紅色App主題,在改成綠色桌布之後,App主題也相應的變成綠色了。
模擬器演示略微小卡...
3、介紹
這個效果主要是使用了Material You中的動態顏色功能。
3.1、什麼是Material You
Material You
也稱Material3或M3,是第三代Material Design設計語言。
Material You將顏色重新定義為更加個性化的體驗,助力於構建出色且富有表現力的應用。
3.2、什麼是動態顏色
動態顏色(Dynamic Color
)是Material You的關鍵部分,通過動態配色提取演算法從使用者的桌布中派生出顏色方案,且符合無障礙使用的標準,亦或是自定義的個性化顏色方案,然後應用於系統UI和應用程式,從而讓裝置變得更加個性化。
3.3、動態顏色的原理是什麼
- 首先,從使用者的桌布上提取一種源顏色,並推算出5中關鍵顏色,比如primary、Secondary、Tertiary等。
- 然後,將每個關鍵顏色轉化為由13種色調組成的調色盤,且每種色調會生成對應的淺、深色方案。
- 最後,通過系統Token將從桌布提取的顏色方案和App Theme關聯起來,在DynamicColorsActivityLifecycleCallbacks中判斷是否需要覆蓋。
4、實現
4.1、遷移到M3
4.1.1、更新Gradle依賴
升級material
庫版本到1.5.0
及以上
kotlin
implementation 'com.google.android.material:material:1.5.0'
4.1.2、修改版本
修改compileSdkVersion
和targetSdkVersion
到31
及以上
kotlin
android {
compileSdkVersion 31
defaultConfig {
applicationId "com.yechaoa.materialdesign"
minSdkVersion 23
targetSdkVersion 31
...
}
...
}
備註:在Android12
上,為增強安全性,需要對所有的四大元件(帶有intent-filter)新增android:exported
屬性。
4.1.3、修改App主題
將Theme.AppCompat.*
或Theme.MaterialComponents.*
改為 Theme.Material3.*
```kotlin
</style>
```
4.2、新增動態顏色
4.2.1、應用動態顏色
```kotlin class App: Application() {
override fun onCreate() {
super.onCreate()
// apply dynamic color
DynamicColors.applyToActivitiesIfAvailable(this)
}
}
``
在
Application`中應用動態顏色能力,除applyToActivitiesIfAvailable(@NonNull Application application)方法之外主要還有:
- applyToActivitiesIfAvailable(@NonNull Application application, @StyleRes int theme) 第二個引數表示自定義的覆蓋系統的theme
- applyIfAvailable(@NonNull Activity activity) 或是某一個Activity
- applyIfAvailable(@NonNull Activity activity, @StyleRes int theme) 或是隻有某一個Activity覆蓋
- 等等
這裡直接整個App都使用動態顏色。也可以在App中通過開關的形式來決策。
4.2.2、註冊到manifest
通過android:name
來註冊我們自定義的Application
kotlin
<application
android:name=".App"
...
android:theme="@style/AppTheme">
...
</application>
4.2.3、使用動態顏色
我們過去在使用顏色時可能是硬編碼
,比如這樣:
kotlin
android:background="@color/colorPrimary"
現在顏色的色值不確定了,應改為動態訪問
的方式:
kotlin
android:background="?attr/colorPrimary"
OK,至此已經可以在Android 12 上試試動態顏色的效果了。
Author:yechaoa
4.3、Material Theme Builder
在4.2.1
中,我們提到applyIfAvailable(@NonNull Activity activity, @StyleRes int theme) ,可以通過第二個引數只給某一個Activity覆蓋Theme。
場景還是有很多的,比如某個特殊的頁面就是需要不一樣的主題,再比如在國慶節這天App的首頁一定要是紅色的。
官方其實也考慮到了這種場景,並提供了Material Theme Builder
(Figma&Web)工具進行視覺化自定義。
下面主要介紹Material Theme Builder在Web上的使用。
4.3.1、桌布預覽
截圖是自帶的效果,在右下角可以點選add your wallpaper
新增你的桌布並檢視顯示效果。
4.3.2、自定義Theme
點選頂部的CUSTOM
Tab可以進入自定義頁面。
左邊的核心顏色可以自定義修改,並可以新增擴充套件顏色。
中間是實時效果,右邊是調色盤。
在右上角有一個EXPORT
匯出按鈕
除了可以應用Android,還有Flutter
和Web
。
匯出的檔案包含日間模式和夜間模式的Color和Theme檔案,可以直接copy到專案中使用。
4.3.3、Theme覆蓋
基於規範,覆蓋的主題最好是加上overlay
標示,比如:
kotlin
<style name="AppTheme.Overlay" parent="ThemeOverlay.Material3.DynamicColors.DayNight">
<item name="colorPrimary">@color/overlay_colorPrimary</item>
...
</style>
程式碼應用:
kotlin
DynamicColors.applyToActivitiesIfAvailable(this, R.style.AppTheme.Overlay)
也可以新增一個開關,讓使用者可以在動態顏色和自定義顏色來回切換。
4.4、是否支援動態顏色
基於Android的開源,可能並不是每個廠商的Android12裝置都支援動態顏色。
所以官方也提供了Api進行判斷:
kotlin
@SuppressLint("DefaultLocale")
@ChecksSdkIntAtLeast(api = VERSION_CODES.S)
public static boolean isDynamicColorAvailable() {
if (VERSION.SDK_INT < VERSION_CODES.S) {
return false;
}
DeviceSupportCondition deviceSupportCondition =
DYNAMIC_COLOR_SUPPORTED_MANUFACTURERS.get(Build.MANUFACTURER.toLowerCase());
if (deviceSupportCondition == null) {
deviceSupportCondition = DYNAMIC_COLOR_SUPPORTED_BRANDS.get(Build.BRAND.toLowerCase());
}
return deviceSupportCondition != null && deviceSupportCondition.isSupported();
}
截止目前,跟進的廠商有:
kotlin
deviceMap.put("oppo", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("realme", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("oneplus", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("vivo", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("xiaomi", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("motorola", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("itel", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("tecno mobile limited", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("infinix mobility limited", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("hmd global", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("sharp", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("sony", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("tcl", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("lenovo", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("lge", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("google", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("robolectric", DEFAULT_DEVICE_SUPPORT_CONDITION);
deviceMap.put("samsung", SAMSUNG_DEVICE_SUPPORT_CONDITION);
5、總結
總的來說,這個功能還是非常nice的,可以讓你的App在Android12上表現的更加個性化且富有表現力。
但還是能識別出很多成本的,比如targetSdkVersion升級到31,Theme遷移到Material3,以及升級後的整包迴歸。
所以,個人建議,對於老專案最好是申請專項來做,其實更建議用新專案來嚐鮮。
6、Github
http://github.com/yechaoa/MaterialDesign
7、文件
8、最後
寫作不易,感謝點贊支援 ^ - ^