Compose -- Theme主题,还怕你的App不够花里胡哨么?
Posted 乐翁龙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Compose -- Theme主题,还怕你的App不够花里胡哨么?相关的知识,希望对你有一定的参考价值。
文章目录
Compose主题
Compose提供了系统化的方法来帮助我们自定义主题,这让我们在实现暗黑主题以及其他颜色主题的时候非常非常的方便。
需求一览
这节的需求很简单,我们的App需要有蓝,红,绿,黄四种主题色,在点击tab的时候分别切换不同的主题色,大致效果如下所示。
默认的主题
比如我们的工程名叫ComposeComing,那么工程建好后默认的Activity中会有如下代码:
setContent
ComposeComingTheme
Surface(color = MaterialTheme.colors.background)
上面有两处代码很可疑:
- ComposeComingTheme
- MaterialTheme.colors.background
首先这个 ComposeComingTheme() 函数我们点进去看下,你会发现该组合函数在 包名.ui.theme 文件夹下的 Theme.kt 文件中:
private val DarkColorPalette = darkColors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200
)
private val LightColorPalette = lightColors(
primary = Purple500,
primaryVariant = Purple700,
secondary = Teal200
)
@Composable
fun ComposeComingTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
)
val colors = if (darkTheme)
DarkColorPalette
else
LightColorPalette
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
通过上述代码,我们可以了解到:ComposeComingTheme 该组合函数在 MaterialTheme 上构建而成,MaterialTheme由colors、typography、shapes属性组成。然后该组合函数默认根据系统 是否是暗黑主题 将 颜色属性 进行了不同的定义。如果是暗黑主题使用DarkColorPalette,否则使用LightColorPalette。darkColors和lightColors都继承自Colors,并有相关的默认颜色值。所以我们的需求-自定义不同的主题颜色可以在这里进行突破了。
Colors中的所有可配的值如下所示:
@Stable
class Colors(
primary: Color,
primaryVariant: Color,
secondary: Color,
secondaryVariant: Color,
background: Color,
surface: Color,
error: Color,
onPrimary: Color,
onSecondary: Color,
onBackground: Color,
onSurface: Color,
onError: Color,
isLight: Boolean
)
而 MaterialTheme.colors.background 中最终调用的就是相关主题中设置的Colors的 background 属性值。
自定义主题
接下来我们根据需求进行主题的自定义,首先给大家点颜色看看,在ui.theme文件夹下的Color.kt文件中添加如下颜色:
val blue = Color(0xFF579DFD)
val red = Color(0xFFEB685E)
val green = Color(0xFF27BA6A)
val yellow = Color(0xFFFFCB1F)
然后在ui.theme文件夹下的Theme.kt文件中自定义主题,在这里我们统一使用了lightColors,然后根据传递进来的主题的名称将primary属性设置为了不同的颜色,如下所示:
@Composable
fun MyAppTheme(
themeName: String = "blue",
content: @Composable() () -> Unit
)
val colors = when (themeName)
"red" -> lightColors(primary = red)
"green" -> lightColors(primary = green)
"yellow" -> lightColors(primary = yellow)
else -> lightColors(primary = blue)
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
这样我们主题就已经定义好了,虽然只有primary属性会根据不同主题变化,但是这足够我们演示了。
接下来是TabRow的实现,我们将TabRow的背景颜色 backgroundColor 设置为刚定义的 primary 的颜色,点击不同tab的时候设置不同的主题,并将点击事件提升到上层处理,代码如下所示,:
@Composable
fun MyTabRow(
onTabItemClick: (name: String) -> Unit,
indexDefault: Int = 0
)
val indexState = remember
mutableStateOf(indexDefault)
val colorsTab = arrayOf("blue", "red", "green", "yellow")
TabRow(
selectedTabIndex = indexState.value,
modifier = Modifier
.fillMaxWidth()
.height(46.dp),
backgroundColor = MaterialTheme.colors.primary
)
for ((index, name) in colorsTab.withIndex())
Tab(
selected = index == indexState.value,
onClick =
indexState.value = index
onTabItemClick(colorsTab[index])
,
modifier = Modifier.fillMaxHeight(),
)
Text(
text = name,
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(),
textAlign = TextAlign.Center
)
先来预览下吧,我们在自定的主题MyAppTheme中组合MyTabRow,然后给定相关的主题颜色,这里默认预览红色和绿色的主题:
@Preview(showBackground = true)
@Composable
fun RedThemePreview()
MyAppTheme(themeName = "red")
MyTabRow(
onTabItemClick = ,
indexDefault = 1
)
@Preview(showBackground = true)
@Composable
fun GreenThemePreview()
MyAppTheme(themeName = "green")
MyTabRow(
onTabItemClick = ,
indexDefault = 2
)
预览效果如下所示:
实现需求
预览图没有问题,接下来就是整体的实现了,反正就一点 – 数据驱动,视图自响应,在onCreate()函数中:
setContent
val themeName = remember
mutableStateOf("blue")
MyAppTheme(themeName = themeName.value)
Column
MyTabRow(onTabItemClick =
themeName.value = it
)
这样,我们点击不同tab的时候,改变themeName的值,MyAppTheme会自动根据相应的值进行主题的切换,是不是就达到了如下效果呢:
Colors属性不够用?
上述需求实在是太简单了,但是实际开发中我们可能有很多种地方都定义了不同的颜色,而Colors中只提供了12个相关颜色的定义,不够用啊!!!
那怎么办呢?扩展,字面意义上的扩展,同时也是kotlin中的扩展。直接给Colors扩展相关的属性:
val Colors.myTabRowBackground: Color
@Composable get() = if (isLight) red else blue
但是这种方式明显有弊端,就是只能根据是否是暗黑主题进行颜色的配置,无法支持到我们上述的那么多种主题,而且也比较麻烦。
而且我查遍了全网也没有见到使用var来进行属性扩展的示例,难道是不支持么?扔物线的视频让我自己研究,其他培训机构的老师讲到这里直接卡壳了。我需要给这个扩展的属性进行赋值和取值的操作,求指点。
以上是关于Compose -- Theme主题,还怕你的App不够花里胡哨么?的主要内容,如果未能解决你的问题,请参考以下文章
Compose -- Theme主题,还怕你的App不够花里胡哨么?
Compose -- Theme主题,还怕你的App不够花里胡哨么?
拥有了 Compose -- Theme主题,还怕你的App不够花里胡哨么?
使用Material Design 创建App翻译系列----材料主题的使用(Using Material Theme)