Search code examples
androidkotlinandroid-jetpack-composecomposable

How do I make the UI update when changing values in a List?


I want to change the colour of some things in my Jetpack Compose project, but I simply can't get it to work. I'm trying to make a small app for myself where I have a 3x3 grid in the middle (that's a LazyVerticalGrid) that I want to change the colour of. My code so far is as follows:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            RubiksRaceTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Column(
                        horizontalAlignment = Alignment.CenterHorizontally,
                        verticalArrangement = Arrangement.Center,
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(top = 30.dp)
                    ) {
                        Image(painter = painterResource(id = R.drawable.rrlogo),
                            contentDescription = "Logo",
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(60.dp)
                                .scale(2f)
                        )
                        val cols = remember { mutableStateOf(RRCols) }
                        RRGrid(cols)
                        Button(onClick = { shuffle(cols) },
                            colors = ButtonDefaults.buttonColors(
                                contentColor = Color(0xFFFFFFFF),
                                backgroundColor = RRBlue
                            ),
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(horizontal = 8.dp, vertical = 50.dp)
                                .background(RRInv)
                                .size(100.dp)
                        ) {
                            Text(text = "SHUFFLE",
                                fontSize = 36.sp
                                )
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun RRGrid (rrCols: MutableState<MutableList<String>>) {
    Box(contentAlignment = Alignment.Center,
        modifier = Modifier
            .fillMaxWidth()
    ) {
        LazyVerticalGrid(columns = GridCells.Fixed(3),
            contentPadding = PaddingValues(12.dp)
        ) {
            items(rrCols.value) {
                val col = RRColMap[it] ?: RRWhite
                Card(modifier = Modifier
                    .padding(4.dp)
                    .background(col)
                    .size(110.dp)
                ) {
                    Box(modifier = Modifier
                        .background(col))
                }
            }
        }
    }
}

fun shuffle(rrCols: MutableState<MutableList<String>>) {
    var check = mutableListOf<Int>(0,0,0,0,0,0)
    for (i in 0..8) {
        var num = Random.nextInt(0,6)
        while (check[num] >= 4) {
            num = Random.nextInt(0,6)
        }
        check[num] += 1
        rrCols.value[i] = RRNumCol[num] ?: "w"
    }
    Log.v("SET", RRCols.toString())

}

And a data.kt file (which is really bad) with

var RRCols = mutableListOf("w", "w", "w", "w", "w", "w", "w", "w", "w")

val RRColMap = mapOf(
    "w" to RRWhite,
    "r" to RRRed,
    "b" to RRBlue,
    "g" to RRGreen,
    "o" to RROrange,
    "y" to RRYellow
)

val RRNumCol = mapOf(
    0 to "w",
    1 to "r",
    2 to "b",
    3 to "g",
    4 to "o",
    5 to "y"
)

The Log.v at the bottom prints out a new list everytime the button is pressed, but nothing changes when I change the values. This is even after looking around a lot and using a val cols = remember { mutableStateOf(RRCols) }.

How do I fix this so that the RRGrid composable is updated whenever I change the value inside the remember.

I've searched around, tried using GitHub CoPilot, New Bing, and read documentation. But I can't see what I'm doing wrong since the list clearly changes its values.


Solution

  • Don't mutate your list, assign a new list to the remembered variable, or use mutableStateListOf instead.