Home > other >  jetpack compose removing elements from list of text fields
jetpack compose removing elements from list of text fields

Time:11-01

list of text fields.

I want my code to remove elements from list of text fields properly. Each element has an X button to remove it's text field. If I start removing elements from the bottom it works but it doesn't work for removing random elements I want to use forEachIndexed for displaing the list Please help me with solving this problem. I've been trying to do this for some time but every trial is unsuccessful.

This is a piece of code that I've managed to write but removing elements doesn't work properly

val listOfWords = mutableStateListOf<String>()


@Composable
fun Main() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState()),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        Text(
            text = "Words",
            modifier = Modifier.padding(0.dp, 0.dp, 0.dp, 4.dp),
            style = MaterialTheme.typography.h6
        )

            listOfWords.forEachIndexed { index, word ->
                Input(word, 30, "Word", 1,
                    {newWord ->
                        listOfWords[index] = newWord
                        Log.d("text ",word)
                    },
                    {
                        listOfWords.removeAt(index)
                    }
                )
            }

        IconButton(
            onClick = {
                listOfWords.add("")
            }
        ) {
            Icon(
                imageVector = Icons.Filled.Add,
                contentDescription = "Add"
            )
        }


    }
}

@Composable
fun Input(
    word: String,
    maxChar: Int,
    label: String,
    maxLines: Int,
    onEdit: (word: String) -> (Unit),
    onRemove: () -> (Unit)
) {
    var text by remember { mutableStateOf(word) }
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(8.dp, 0.dp, 8.dp, 0.dp)
    ) {
        OutlinedTextField(
            value = text,
            onValueChange = {
                if (it.length <= maxChar) text = it
                onEdit(text)
            },
            modifier = Modifier.fillMaxWidth(),
            label = { Text(label) },
            leadingIcon = {
                Icon(Icons.Default.Edit, null)
            },
            trailingIcon = {
                IconButton(onClick = {
                    onRemove()
                }) {
                    Icon(
                        imageVector = Icons.Default.Clear,
                        contentDescription = "Back"
                    )
                }
            },
            maxLines = maxLines
        )

        Text(
            text = "${text.length} / $maxChar",
            textAlign = TextAlign.End,
            style = MaterialTheme.typography.caption,
            modifier = Modifier
                .fillMaxWidth()
                .padding(end = 16.dp)
        )
    }
}


CodePudding user response:

Have you tried doing the following instead?

listOfWords.forEachIndexed { index, word ->
    ... // rest of code
    {
        listOfWords.removeAt(index)
    }

CodePudding user response:

The problem is here,

var text by remember { mutableStateOf(word) }

use the word parameter as key for remember to re-calculate every composition pass (i.e when you add/remove or typed a value in the TextField), and your code should probably work as you expected.

var text by remember(word) { mutableStateOf(word) }

Without supplying a key to Input's remember, compose will not be able refresh/update your Input states visually during Main's re-composition every time an Input is removed.

  • Related