在最近的学习过程中,有个主题色的选择更换需求,学习完成后就来这发文章啦!完整代码 在这。
这里简单的模拟了一下主题色的更换,可以看到颜色更换和持久化保存都没问题。
更换颜色最主要的当然是选择颜色啦,代码如下:
@OptIn(ExperimentalFoundationApi::class)
@androidx.compose.runtime.Composable
fun ColorPicker(
colorList: List<Color>,
currentShowColor: Color,
onColorConfirm: (Int) -> Unit
) {
var currentColor by remember {
mutableStateOf(currentShowColor)
}
LazyVerticalGrid(
// 单元格展现形式
cells = GridCells.Fixed(5),
verticalArrangement = Arrangement.Center,
horizontalArrangement = Arrangement.Center
) {
itemsIndexed(colorList) { index, item ->
Surface(
modifier = Modifier
//宽高比
.aspectRatio(1f)
.padding(4.dp)
.clickable {
currentColor = item
onColorConfirm(index)
},
shape = CircleShape,
color = item,
border = BorderStroke(1.dp, Color.Black),
) {
if (currentColor == item) {
Icon(Icons.Default.Favorite, null, modifier = Modifier.padding(10.dp))
}
}
}
}
}
这里传入三个参数,colorList 是所有颜色的一个列表,currentShowColor 是当前展示的颜色(即效果展示中的背景色),onColorConfirm 是确认更换颜色在后边会用到。颜色以 LazyVerticalGrid 加 Surface 进行展现,这里要注意在 modifier 加上 .aspectRatio(1f) 即宽高比,否则你的效果会是这样的:
Icon 则用来标记选中或点击了哪个颜色, currentColor 用于触发它的重绘。除此以外,还有一个点要注意在新版中上面这种 LazyVerticalGrid 已经被弃用,可以用下面这种代替(大体一样):
androidx.compose.foundation.lazy.grid.LazyVerticalGrid(
columns = androidx.compose.foundation.lazy.grid.GridCells.Fixed(5),
contentPadding = PaddingValues(5.dp),
verticalArrangement = Arrangement.Center,
horizontalArrangement = Arrangement.Center,
) { ... }
从效果图可以看到展现颜色选择器这部分我是用对话框来实现,如下:
@Composable
fun ColorPickerDialog(
textContent: @Composable (() -> Unit),
onConfirm: () -> Unit,
onDismiss: () -> Unit
) {
AlertDialog(
onDismissRequest = onDismiss,
title = { Text(text = "颜色选择器") },
// 这里上下的 text 可不同哦
// text: @Composable (() -> Unit)? = null,
text = {
textContent()
},
// 确认按钮
confirmButton = {
TextButton(
onClick = {
onConfirm()
onDismiss()
}
) {
Text("确定")
}
},
// 取消按钮
dismissButton = {
TextButton(
onClick = onDismiss
) {
Text("取消")
}
}
)
}
三个参数,textContent 即对话框的内容(稍后会传入上面我们写好的颜色选择),onConfirm 确认功能(确认更换颜色和颜色的持久化),onDismiss 取消功能(没啥用就关闭对话框)。
上面已经写好了主要部分,现在将他们组合起来用一下:
@Composable
fun Test(
showColor: MutableState<Color>,
colorList: List<Color>
) {
var showDialogState by remember {
mutableStateOf(false)
}
val context = LocalContext.current
var currentColorIndex = 0
Surface(
modifier = Modifier.fillMaxSize(),
color = showColor.value
) {
TextButton(onClick = {
showDialogState = true
}) {
Text("点我点我")
}
if (showDialogState) {
ColorPickerDialog(
{ ColorPicker(colorList, showColor.value) { currentColorIndex = it } },
{
// 确定更换颜色
showColor.value = colorList[currentColorIndex]
// 持久化保存
SpMMKVUtil.put("color", currentColorIndex)
Toast.makeText(context, "早啊", Toast.LENGTH_SHORT).show()
},
{ showDialogState = false }
)
}
}
}
这里 showDialogState 用于控制对话框的显隐,currentColorIndex 作为确认按钮和颜色选择直接的中间商,帮忙暂时存一下。另外这里要实现开头那样的效果的话不应该直接将 showColor: MutableState 传入 ColorPicker (我之前就是这么干的)。如果将它传入并用它来更换颜色的话,我们点击一个颜色它就变成了那个颜色,这样的话确认按钮就可以删掉了。其实这样也挺好,有的软件就是这样干的。看看这样的效果:
从代码中可以看到这里用了一个 SpMMKVUtil 来持久化,它是封装了 MMKV 的一个工具,( MMKV 是一个轻量级高效存储数据库,腾讯开发的哦,存储读写效率高, 最近刚学就用了一下),推荐大家也可以去学一下,网上教程一大把,这就不说了
先扔代码:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val colorList = listOf(
Color(0xFF8FDAFC),
Color(0xFFB34D9E),
Color(0xFF44BBA3),
Color(0xFF8AB34D),
Color(0xFFA25E5E),
Color(0xFF778888),
Color(0xFFCC3352),
)
// val showColor = remember {
// mutableStateOf(colorList[SpMMKVUtil.getInt("color")!!])
// }
val showColor: MutableState<Color> by lazy {
mutableStateOf(colorList[SpMMKVUtil.getInt("color") ?: 0])
}
setContent {
MyColorPicker2Theme {
Surface(
modifier = Modifier.fillMaxSize(),
color = Color.White
) {
Test(showColor, colorList)
}
}
}
}
}
colorList 就是我们的颜色列表用来展示和选择的。这里的注释应该要注意到,报错如下:
它只能在带有 @Composable 注释的时候才能用。所以用个 lazy 来解决一下。到这所以代码都讲完了。
记得添加 MMKV 依赖
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.GridCells
import androidx.compose.foundation.lazy.LazyVerticalGrid
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.example.mycolorpicker2.SpMMKVUtil
import com.example.mycolorpicker2.ui.theme.MyColorPicker2Theme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val colorList = listOf(
Color(0xFF8FDAFC),
Color(0xFFB34D9E),
Color(0xFF44BBA3),
Color(0xFF8AB34D),
Color(0xFFA25E5E),
Color(0xFF778888),
Color(0xFFCC3352),
)
val showColor = remember {
mutableStateOf(colorList[SpMMKVUtil.getInt("color")!!])
}
// val showColor: MutableState by lazy {
// mutableStateOf(colorList[SpMMKVUtil.getInt("color") ?: 0])
// }
setContent {
MyColorPicker2Theme {
Surface(
modifier = Modifier.fillMaxSize(),
color = Color.White
) {
Test(showColor, colorList)
}
}
}
}
}
@Composable
fun Test(
showColor: MutableState<Color>,
colorList: List<Color>
) {
var showDialogState by remember {
mutableStateOf(false)
}
val context = LocalContext.current
var currentColorIndex = 0
Surface(
modifier = Modifier.fillMaxSize(),
color = showColor.value
) {
TextButton(onClick = {
showDialogState = true
}) {
Text("点我点我")
}
if (showDialogState) {
ColorPickerDialog(
{ ColorPicker(colorList, showColor.value) { currentColorIndex = it } },
{
// 确定更换颜色
showColor.value = colorList[currentColorIndex]
// 持久化保存
SpMMKVUtil.put("color", currentColorIndex)
Toast.makeText(context, "早啊", Toast.LENGTH_SHORT).show()
},
{ showDialogState = false }
)
}
}
}
@Composable
fun ColorPickerDialog(
textContent: @Composable (() -> Unit),
onConfirm: () -> Unit,
onDismiss: () -> Unit
) {
AlertDialog(
onDismissRequest = onDismiss,
title = { Text(text = "颜色选择器") },
// 这里上下的 text 可不同哦
// text: @Composable (() -> Unit)? = null,
text = {
textContent()
},
// 确认按钮
confirmButton = {
TextButton(
onClick = {
onConfirm()
onDismiss()
}
) {
Text("确定")
}
},
// 取消按钮
dismissButton = {
TextButton(
onClick = onDismiss
) {
Text("取消")
}
}
)
}
@OptIn(ExperimentalFoundationApi::class)
@androidx.compose.runtime.Composable
fun ColorPicker(
colorList: List<Color>,
currentShowColor: Color,
onColorConfirm: (Int) -> Unit
) {
var currentColor by remember {
mutableStateOf(currentShowColor)
}
LazyVerticalGrid(
// 单元格展现形式
cells = GridCells.Fixed(5),
verticalArrangement = Arrangement.Center,
horizontalArrangement = Arrangement.Center
) {
itemsIndexed(colorList) { index, item ->
Surface(
modifier = Modifier
//宽高比
.aspectRatio(1f)
.padding(4.dp)
.clickable {
currentColor = item
onColorConfirm(index)
},
shape = CircleShape,
color = item,
border = BorderStroke(1.dp, Color.Black),
) {
if (currentColor == item) {
Icon(Icons.Default.Favorite, null, modifier = Modifier.padding(10.dp))
}
}
}
}
}
文章就到这,希望对你有帮助,欢迎评论,拜拜!