来自 | Zhujiang的博客地址:
https://juejin.cn/user/3913917127985240


val Purple200 = Color(0xFFBB86FC)
val Purple500 = Color(0xFF6200EE)
val Purple700 = Color(0xFF3700B3)
val Teal200 = Color(0xFF03DAC5)
private val DarkColorPalette = darkColors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200
)
private val LightColorPalette = lightColors(
primary = Purple500,
primaryVariant = Purple700,
secondary = Teal200
)
@Composable
fun PlayAndroidTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
fun lightColors(
primary: Color = Color(0xFF6200EE),
primaryVariant: Color = Color(0xFF3700B3),
secondary: Color = Color(0xFF03DAC6),
secondaryVariant: Color = Color(0xFF018786),
background: Color = Color.White,
surface: Color = Color.White,
error: Color = Color(0xFFB00020),
onPrimary: Color = Color.White,
onSecondary: Color = Color.Black,
onBackground: Color = Color.Black,
onSurface: Color = Color.Black,
onError: Color = Color.White
): Colors
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// 使用主题
PlayAndroidTheme {
NavGraph()
}
}
}
// 颜色使用
MaterialTheme.colors.primary
// 形状使用
MaterialTheme.shapes.large
// 字体类型使用
MaterialTheme.typography.body1
/ 解决 / 如何切换主题 首先需要思考如何来进行主题的切换,整个主题肯定使用在项目的开始——启动 Activity 中,但切换主题的页面肯定不在一块,那这个时候应该如何在切换主题页面切换了之后让 Activity 知道呢? 最开始的时候我的想法还是不够 Compose ,我想的是使用广播,在切换主题页面点击之后发送一个广播,然后在 Activity 中进行接收,然后接收到之后刷新。我确实这样做了,功能也确实实现了,但是总感觉哪里不对,感觉 Compose 中不应该这样才对。 中午在食堂吃饭的时候突然想到:Compose 中全部都是以状态驱动 UI 改变的,我直接将主题切换设置成一个状态不得了! 开搞 说干就干,首先先来设置下咱们默认的几套主题吧。 // 天蓝色
const val SKY_BLUE_THEME = 0
// 灰色
const val GRAY_THEME = 1
// 深蓝色
const val DEEP_BLUE_THEME = 2
// 绿色
const val GREEN_THEME = 3
// 紫色
const val PURPLE_THEME = 4
// 橘黄色
const val ORANGE_THEME = 5
// 棕色
const val BROWN_THEME = 6
// 红色
const val RED_THEME = 7
// 青色
const val CYAN_THEME = 8
// 品红色
const val MAGENTA_THEME = 9这里为了之后代码简单点没有使用枚举,其实都差不多的。 然后添加一个主题的状态: /**
* 主题状态
*/
val themeTypeState: MutableState<Int> by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
mutableStateOf(getDefaultThemeId())
}可以看到主题状态中有一个名为 getDefaultThemeId 的方法,用来获取默认主题 ID,来看下吧。 /**
* 获取当前默认主题
*/
fun getDefaultThemeId(): Int = DataStoreUtils.getSyncData(CHANGED_THEME, SKY_BLUE_THEME)这里使用了 DataStore 来进行数据的存取,DataStore 也是 Jetpack 中的一员。然后修改下主题方法: @Composable
fun PlayAndroidTheme(
themeId: Int = 0,
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colors = if (darkTheme) {
playDarkColors()
} else {
getThemeForThemeId(themeId)
}
MaterialTheme(
colors = colors,
typography = typography,
shapes = Shapes,
content = content
)
}可以看到上面添加了一个参数 themeId 用来表示当前需要使用的主题 id,getThemeForThemeId 方法用来通过主题 ID 来获取需要的主题颜色集,来看下实现吧。 /**
* 通过主题 ID 来获取需要的主题
*/
private fun getThemeForThemeId(themeId: Int) = when (themeId) {
SKY_BLUE_THEME -> {
playLightColors(
primary = primaryLight
)
}
GRAY_THEME -> {
playLightColors(
primary = gray_theme
)
}
// 别的主题类似,篇幅原因省略
}接下来修改下 Activity 中的调用吧。 PlayAndroidTheme(themeTypeState.value) {
NavGraph()
}由于 themeTypeState是一个State,所以当它的值改变的时候,就会自动刷新UI。 / 收尾 / 创建主题列表 先做下准备工作,先来创建一个用来存放主题信息的实体类吧。 data class ThemeModel(val color: Color, val colorId: Int, val colorName: String) 接下来将咱们添加的主题放到一个 List 中。 // 主题model列表
private val themeList = arrayListOf(
ThemeModel(primaryLight, SKY_BLUE_THEME, "天蓝色"),
ThemeModel(gray_theme, GRAY_THEME, "灰色"),
ThemeModel(deep_blue_theme, DEEP_BLUE_THEME, "深蓝色"),
ThemeModel(green_theme, GREEN_THEME, "绿色"),
ThemeModel(purple_theme, PURPLE_THEME, "紫色"),
ThemeModel(orange_theme, ORANGE_THEME, "橘黄色"),
ThemeModel(brown_theme, BROWN_THEME, "棕色"),
ThemeModel(red_theme, RED_THEME, "红色"),
ThemeModel(cyan_theme, CYAN_THEME, "青色"),
ThemeModel(magenta_theme, MAGENTA_THEME, "品红色"),
)创建主题切换页面 万事具备,只欠东风。现在主题这块已经全部准备好了,只需要再创建一个主题切换的页面,点击的时候保存下来主题 ID 并刷新下 themeTypeState 的值即可。 由上图可以看出这个布局最好使用 LazyVerticalGrid,然后设置下一行放 5 个 item 即可。 LazyVerticalGrid(
cells = GridCells.Fixed(5),
modifier = Modifier.padding(horizontal = 10.dp)
) {
items(themeList) { item: ThemeModel ->
ThemeItem(playTheme, item) {
val playTheme = item.colorId
themeTypeState.value = playTheme
DataStoreUtils.putSyncData(CHANGED_THEME, playTheme)
}
}
}OK了,结束了,这样就可以了,已经可以实现文章开头 Gif 图的那种效果了。 / 结局 / 这么快就到结局了,还有点不舍,哈哈哈。光顾着写实现了,还没放 Github 地址呢,在这里: https://github.com/zhujiang521/PlayAndroid
---END---
版权申明:内容来源网络,版权归原创者所有。除非无法确认,都会标明作者及出处,如有侵权,烦请告知,我们会立即删除并致歉!
原文始发于微信公众号(互联网程序员):Compose主题切换,让你的APP也能一键换肤
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/23973.html