利用Jetpack Compose實(shí)現(xiàn)主題切換功能
前言
新建的Compose
項(xiàng)目默認(rèn)的 Material
主題為我們提供了一些顏色,但對(duì)我這種花里胡哨的人來說根本不夠呀。 所以系統(tǒng)提供的主題不能滿足需求時(shí)候可以自己配置主題
compose 實(shí)現(xiàn)換膚很簡(jiǎn)單
之前xml方法可復(fù)雜了
通過LayoutInflater調(diào)用inflate方法加載XML布局,在inflate方法中有一個(gè)createViewFromTag,再根據(jù)LayoutInflater當(dāng)中Factory的接口類型(Factory or Factory2)調(diào)用CreateView方法加載,其中通過“name”可以得到加載的控件Tag,再通過AttributeSet得到控件的全部屬性最后再切換背景顏色
這是默認(rèn)的代碼,我們要改造一下
color.kt
先是用全局靜態(tài)變量寫一套顏色變量
val statusBarColorLight = Color(0xFFFFFFFF) val statusBarColorDark = Color(0xFF1C1C28) val backgroundColorLight = Color(0xFFF2F2F6) val backgroundColorDark = Color(0xFF1C1C28) val textPrimaryLight = Color(0xFF333333) val textPrimaryDark = Color(0xFFE8E8F0) val textSecondaryLight = Color(0xFF999999) val textSecondaryDark = Color(0xFF999999)
...此處省略500字 哈哈
Theme.kt
定義各種各樣的顏色名稱
@Stable class AppColors( statusBarColor: Color, themeUi: Color, background: Color, listItem: Color, divider: Color, textPrimary: Color, textSecondary: Color, mainColor: Color, card: Color, icon: Color, info: Color, warn: Color, success: Color, error: Color, primaryBtnBg: Color, secondBtnBg: Color, hot: Color, placeholder: Color, )
接著引入mutableStateOf,來標(biāo)明這個(gè)Color是有狀態(tài)的,如果狀態(tài)發(fā)生了改變,所有引用這個(gè)顏色的控件都發(fā)生了改變,都需要重新繪制!
var statusBarColor: Color by mutableStateOf(statusBarColor) internal set var themeUi: Color by mutableStateOf(themeUi) internal set var background: Color by mutableStateOf(background) private set var listItem: Color by mutableStateOf(listItem) private set var divider: Color by mutableStateOf(divider) private set var textPrimary: Color by mutableStateOf(textPrimary) internal set var textSecondary: Color by mutableStateOf(textSecondary) private set var mainColor: Color by mutableStateOf(mainColor) internal set var card: Color by mutableStateOf(card) private set var icon: Color by mutableStateOf(icon) private set var info: Color by mutableStateOf(info) private set var warn: Color by mutableStateOf(warn) private set var success: Color by mutableStateOf(success) private set var error: Color by mutableStateOf(error) private set var primaryBtnBg: Color by mutableStateOf(primaryBtnBg) internal set var secondBtnBg: Color by mutableStateOf(secondBtnBg) private set var hot: Color by mutableStateOf(hot) private set var placeholder: Color by mutableStateOf(placeholder) private set
復(fù)制粘貼就行啦
接著定義兩套主題 白天和黑夜
你永遠(yuǎn)不懂我傷悲
像白天不懂夜的黑
//夜色主題 private val DarkColorPalette = AppColors( statusBarColor = statusBarColorDark, themeUi = themeColor, background = backgroundColorDark, listItem = listItemDark, divider = dividerDark, textPrimary = textPrimaryDark, textSecondary = textSecondaryDark, mainColor = black3, card = black3, icon = grey1, info = info, warn = warn, success = green3, error = red2, primaryBtnBg = backgroundColorDark, secondBtnBg = black3, hot = red, placeholder = grey1, ) //白天主題 private val LightColorPalette = AppColors( statusBarColor = statusBarColorLight, themeUi = themeColor, background = backgroundColorLight, listItem = listItemLight, divider = dividerLight, textPrimary = textPrimaryLight, textSecondary = textSecondaryLight, mainColor = white, card = white1, icon = inonGary, info = info, warn = warn, success = green3, error = red2, primaryBtnBg = themeColor, secondBtnBg = white3, hot = red, placeholder = white3, )
接著重要的一步來了,如何應(yīng)用這些顏色配色呢?
@Composable fun AppTheme( content: @Composable () -> Unit )
就是這樣
只需要在使用的時(shí)候把控件裝在里面就行了
應(yīng)用之前我們要判斷使用哪個(gè)主題
這里我用深色模式來演示
在Composable下可以用這行代碼判斷當(dāng)前系統(tǒng)處于深色模式
isSystemInDarkTheme()
var LocalAppColors = compositionLocalOf { LightColorPalette } //主題配置單例 @Stable object CustomTheme { val colors: AppColors @Composable get() = LocalAppColors.current //創(chuàng)建主題枚舉 enum class Theme { Light, Dark } }
關(guān)于compositionLocalOf
官方解釋如下: Compose 將數(shù)據(jù)通過組合樹顯式地通過參數(shù)傳遞給可組合函數(shù)。這通常是讓數(shù)據(jù)流過樹的最簡(jiǎn)單和最好的方法。
有時(shí),對(duì)于許多組件需要的數(shù)據(jù),或者當(dāng)組件需要在彼此之間傳遞數(shù)據(jù)但保持該實(shí)現(xiàn)細(xì)節(jié)私有時(shí),此模型可能很麻煩或分解。對(duì)于這些情況,CompositionLocal 可以用作讓數(shù)據(jù)流過組合的隱式方式。
CompositionLocal本質(zhì)上是分層的。當(dāng)CompositionLocal需要將的值限定為組合的特定子層次結(jié)構(gòu)時(shí),它們是有意義的。
必須創(chuàng)建一個(gè)CompositionLocal實(shí)例,該實(shí)例可以被消費(fèi)者靜態(tài)引用。CompositionLocal實(shí)例本身不持有任何數(shù)據(jù),可以將其視為傳遞到樹中的數(shù)據(jù)的類型安全標(biāo)識(shí)符。CompositionLocal工廠函數(shù)采用單個(gè)參數(shù):在CompositionLocal沒有提供程序的情況下使用a 的情況下創(chuàng)建默認(rèn)值的工廠。如果這是您不想處理的情況,則可以在此工廠中引發(fā)錯(cuò)誤。
在樹上的某個(gè)地方,CompositionLocalProvider可以使用一個(gè)組件,它為CompositionLocal. 這通常位于樹的“根”,但也可以在任何地方,也可以在多個(gè)位置使用以覆蓋子樹的提供值。 中間組件不需要知道該CompositionLocal值,并且可以對(duì)其具有零依賴關(guān)系
完整代碼
@Composable fun AppTheme( isDark :Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { val targetColors = if (isDark) DarkColorPalette else LightColorPalette val statusBarColor = animateColorAsState(targetColors.statusBarColor, TweenSpec(600)) val themeUi = animateColorAsState(targetColors.themeUi, TweenSpec(600)) val background = animateColorAsState(targetColors.background, TweenSpec(600)) val listItem = animateColorAsState(targetColors.listItem, TweenSpec(600)) val divider = animateColorAsState(targetColors.divider, TweenSpec(600)) val textPrimary = animateColorAsState(targetColors.textPrimary, TweenSpec(600)) val textSecondary = animateColorAsState(targetColors.textSecondary, TweenSpec(600)) val mainColor = animateColorAsState(targetColors.mainColor, TweenSpec(600)) val card = animateColorAsState(targetColors.card, TweenSpec(600)) val icon = animateColorAsState(targetColors.icon, TweenSpec(600)) val info = animateColorAsState(targetColors.info, TweenSpec(600)) val warn = animateColorAsState(targetColors.warn, TweenSpec(600)) val success = animateColorAsState(targetColors.success, TweenSpec(600)) val error = animateColorAsState(targetColors.error, TweenSpec(600)) val primaryBtnBg = animateColorAsState(targetColors.primaryBtnBg, TweenSpec(600)) val secondBtnBg = animateColorAsState(targetColors.secondBtnBg, TweenSpec(600)) val hot = animateColorAsState(targetColors.hot, TweenSpec(600)) val placeholder = animateColorAsState(targetColors.placeholder, TweenSpec(600)) val appColors = AppColors( statusBarColor = statusBarColor.value, themeUi = themeUi.value, background = background.value, listItem = listItem.value, divider = divider.value, textPrimary = textPrimary.value, textSecondary = textSecondary.value, mainColor = mainColor.value, card = card.value, icon = icon.value, primaryBtnBg = primaryBtnBg.value, secondBtnBg = secondBtnBg.value, info = info.value, warn = warn.value, success = success.value, error = error.value, hot = hot.value, placeholder = placeholder.value ) ProvideWindowInsets { CompositionLocalProvider(LocalAppColors provides appColors) { MaterialTheme( shapes = shapes ) { ProvideWindowInsets(content = content) } } } }
用TweenSpec創(chuàng)建配置了給定持續(xù)時(shí)間、延遲和緩和曲線的效果 反正就是可以在換膚的時(shí)候不會(huì)一閃,會(huì)慢慢切換
最后放在AppTheme下面使用就可以啦
到此這篇關(guān)于利用Jetpack Compose實(shí)現(xiàn)主題切換功能的文章就介紹到這了,更多相關(guān)Jetpack Compose內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文帶你了解Android中的網(wǎng)絡(luò)請(qǐng)求
安卓開發(fā)網(wǎng)絡(luò)請(qǐng)求可謂是安卓開發(fā)的靈魂,如果你不會(huì)網(wǎng)絡(luò)請(qǐng)求,那么你開發(fā)的應(yīng)用軟件就是一具沒有靈魂的枯骨。本文主要為大家介紹的是Android的網(wǎng)絡(luò)請(qǐng)求,感興趣的可以跟隨小編一起學(xué)習(xí)一下2022-11-11Android最新版本開發(fā)環(huán)境搭建圖文教程
這篇文章主要為大家詳細(xì)介紹了Android最新版本開發(fā)環(huán)境搭建圖文教程,重點(diǎn)在于配置JDK,以及adt-bundle,感興趣的小伙伴們可以參考一下2016-07-07Android將應(yīng)用調(diào)試log信息保存在SD卡的方法
Android將應(yīng)用調(diào)試log信息保存在SD卡的方法大家都知道嗎,下面腳本之家小編給大家分享Android將應(yīng)用調(diào)試log信息保存在SD卡的方法,感興趣的朋友參考下2016-04-04Android自定義View原理(實(shí)戰(zhàn))
這篇文章主要介紹了Android自定義View原理,由于Android系統(tǒng)內(nèi)置的View不滿足我們的業(yè)務(wù)需求,變產(chǎn)生了需要自定義View的原因,關(guān)于自定義詳情,需要的小伙伴可以參考下面文章具體詳情2022-05-05android判斷應(yīng)用是否已經(jīng)啟動(dòng)的實(shí)例
這篇文章主要介紹了android判斷應(yīng)用是否已經(jīng)啟動(dòng)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03Android實(shí)現(xiàn)繞球心旋轉(zhuǎn)的引導(dǎo)頁效果
本篇文章主要介紹了Android實(shí)現(xiàn)繞球心旋轉(zhuǎn)的引導(dǎo)頁效果,想要實(shí)現(xiàn)此效果的同學(xué)可以參考一下本文。2016-11-11Android實(shí)現(xiàn)WebView點(diǎn)擊攔截跳轉(zhuǎn)原生
這篇文章主要介紹了Android實(shí)現(xiàn)WebView點(diǎn)擊攔截跳轉(zhuǎn)原生,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03Android直播系統(tǒng)平臺(tái)搭建之圖片實(shí)現(xiàn)陰影效果的方法小結(jié)
這篇文章主要介紹了Android直播系統(tǒng)平臺(tái)搭建, 圖片實(shí)現(xiàn)陰影效果的若干種方法,本文給大家?guī)砣N方法,每種方法通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08Android提高之藍(lán)牙傳感應(yīng)用實(shí)例
這篇文章主要介紹了Android的藍(lán)牙傳感應(yīng)用實(shí)例,對(duì)于Android項(xiàng)目開發(fā)來說非常實(shí)用,需要的朋友可以參考下2014-08-08