利用Jetpack Compose實現(xiàn)主題切換功能
前言
新建的Compose項目默認的 Material 主題為我們提供了一些顏色,但對我這種花里胡哨的人來說根本不夠呀。 所以系統(tǒng)提供的主題不能滿足需求時候可以自己配置主題
compose 實現(xiàn)換膚很簡單
之前xml方法可復雜了
通過LayoutInflater調(diào)用inflate方法加載XML布局,在inflate方法中有一個createViewFromTag,再根據(jù)LayoutInflater當中Factory的接口類型(Factory or Factory2)調(diào)用CreateView方法加載,其中通過“name”可以得到加載的控件Tag,再通過AttributeSet得到控件的全部屬性最后再切換背景顏色

這是默認的代碼,我們要改造一下
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,來標明這個Color是有狀態(tài)的,如果狀態(tài)發(fā)生了改變,所有引用這個顏色的控件都發(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復制粘貼就行啦
接著定義兩套主題 白天和黑夜
你永遠不懂我傷悲
像白天不懂夜的黑
//夜色主題
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,
)接著重要的一步來了,如何應用這些顏色配色呢?
@Composable
fun AppTheme(
content: @Composable () -> Unit
)就是這樣
只需要在使用的時候把控件裝在里面就行了
應用之前我們要判斷使用哪個主題
這里我用深色模式來演示
在Composable下可以用這行代碼判斷當前系統(tǒng)處于深色模式
isSystemInDarkTheme()
var LocalAppColors = compositionLocalOf {
LightColorPalette
}
//主題配置單例
@Stable
object CustomTheme {
val colors: AppColors
@Composable
get() = LocalAppColors.current
//創(chuàng)建主題枚舉
enum class Theme {
Light, Dark
}
}關于compositionLocalOf
官方解釋如下: Compose 將數(shù)據(jù)通過組合樹顯式地通過參數(shù)傳遞給可組合函數(shù)。這通常是讓數(shù)據(jù)流過樹的最簡單和最好的方法。
有時,對于許多組件需要的數(shù)據(jù),或者當組件需要在彼此之間傳遞數(shù)據(jù)但保持該實現(xiàn)細節(jié)私有時,此模型可能很麻煩或分解。對于這些情況,CompositionLocal 可以用作讓數(shù)據(jù)流過組合的隱式方式。
CompositionLocal本質上是分層的。當CompositionLocal需要將的值限定為組合的特定子層次結構時,它們是有意義的。
必須創(chuàng)建一個CompositionLocal實例,該實例可以被消費者靜態(tài)引用。CompositionLocal實例本身不持有任何數(shù)據(jù),可以將其視為傳遞到樹中的數(shù)據(jù)的類型安全標識符。CompositionLocal工廠函數(shù)采用單個參數(shù):在CompositionLocal沒有提供程序的情況下使用a 的情況下創(chuàng)建默認值的工廠。如果這是您不想處理的情況,則可以在此工廠中引發(fā)錯誤。
在樹上的某個地方,CompositionLocalProvider可以使用一個組件,它為CompositionLocal. 這通常位于樹的“根”,但也可以在任何地方,也可以在多個位置使用以覆蓋子樹的提供值。 中間組件不需要知道該CompositionLocal值,并且可以對其具有零依賴關系
完整代碼
@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ù)時間、延遲和緩和曲線的效果 反正就是可以在換膚的時候不會一閃,會慢慢切換


最后放在AppTheme下面使用就可以啦

到此這篇關于利用Jetpack Compose實現(xiàn)主題切換功能的文章就介紹到這了,更多相關Jetpack Compose內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android最新版本開發(fā)環(huán)境搭建圖文教程
這篇文章主要為大家詳細介紹了Android最新版本開發(fā)環(huán)境搭建圖文教程,重點在于配置JDK,以及adt-bundle,感興趣的小伙伴們可以參考一下2016-07-07
Android將應用調(diào)試log信息保存在SD卡的方法
Android將應用調(diào)試log信息保存在SD卡的方法大家都知道嗎,下面腳本之家小編給大家分享Android將應用調(diào)試log信息保存在SD卡的方法,感興趣的朋友參考下2016-04-04
Android實現(xiàn)WebView點擊攔截跳轉原生
這篇文章主要介紹了Android實現(xiàn)WebView點擊攔截跳轉原生,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Android直播系統(tǒng)平臺搭建之圖片實現(xiàn)陰影效果的方法小結
這篇文章主要介紹了Android直播系統(tǒng)平臺搭建, 圖片實現(xiàn)陰影效果的若干種方法,本文給大家?guī)砣N方法,每種方法通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2021-08-08

