10

I've developed a textInput composable with a trailing icon, and I'd like to clear the textInput when the icon is clicked. How can I access the textInput value, so that I can clear it?

    @Composable
fun TextInput(
    myVal: String,
    label: String,
    placeholder: String="",
    helperText: String="",
    errorText: String="",
    onValueChange : (String) -> Unit){
    val hasError = !errorText.isNullOrEmpty()
    val helperColor =  if (hasError)
        Color(0xFFfe392f)
        else
            Color(0xFF5c6a79)

    Row() {
            Column() {
                TextField(
                    colors = TextFieldDefaults.textFieldColors(
                        backgroundColor = Color.Transparent,
                        textColor = Color(0xFF011e41),
                        cursorColor = Color(0xFF011e41),
                        focusedLabelColor = Color(0xFF011e41),
                        unfocusedLabelColor = Color(0xFF011e41),
                        unfocusedIndicatorColor = Color(0xFFebeced),
                        focusedIndicatorColor = Color(0xFF011e41),
                        errorCursorColor = Color(0xFFfe392f),
                        errorIndicatorColor = Color(0xFFfe392f),
                        errorLabelColor = Color(0xFFfe392f)
                    ),
                    value = myVal,
                    onValueChange = onValueChange,
                    label = { Text(label) },
                    placeholder = { Text(placeholder) },
                    isError = hasError,
                    trailingIcon = {Icon(Icons.Filled.Email, contentDescription = "sdsd", modifier = Modifier.offset(x= 10.dp).clickable {
                       //What should I do here?
                    })}
                )

                Text(
                    modifier = Modifier.padding(8.dp),
                    text = if (hasError) errorText else helperText,
                    fontSize = 12.sp,
                    color = helperColor,
                )
            }
    }
}

it's used like this:

var text by remember { mutableStateOf("") }
                    TextInput(myVal = text, label = "label", helperText = "", errorText = "my error") {text = it}
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
Arash Shahzamani
  • 245
  • 5
  • 11

4 Answers4

19

You can use the trailingIcon attribute with a custom clickable modifier.
Something like:

var text by rememberSaveable { mutableStateOf("") }

TextField(
    value = text,
    onValueChange = { text = it },
    trailingIcon = {
        Icon(Icons.Default.Clear,
            contentDescription = "clear text",
            modifier = Modifier
                .clickable {
                    text = ""
                }
        )
    }
)

enter image description here

If you are using a TextFieldValue:

val content = "content"
var text by rememberSaveable(stateSaver = TextFieldValue.Saver) {
    mutableStateOf(TextFieldValue(content))
}

TextField(
    value = text,
    onValueChange = { text = it },
    trailingIcon = {
        Icon(Icons.Default.Clear,
            contentDescription = "clear text",
            modifier = Modifier
                .clickable {
                    text = TextFieldValue("")
                }
        )
    }
)
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • This only works if the text variable refers to a string. If it is a TextFieldValue object, this won't work. TextFieldValue is needed for cases where you need to manipulate the cursor such as placing it at the end of the text. – Johann May 07 '22 at 08:10
  • @Johann In this case you have just to use a different code in the `clickable` modifier of the `trailingIcon`. Answer updated. – Gabriele Mariotti May 07 '22 at 09:11
12

the click handler of your trailing icon has to call the TextField's onValueChange with an empty string:

...
trailingIcon = { 
    Icon(
        Icons.Filled.Email,
        contentDescription = "sdsd",
        modifier = Modifier
            .offset(x= 10.dp)
            .clickable {
                //just send an update that the field is now empty
                onValueChange("") 
            }
        )
}
...
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
Rob Meeuwisse
  • 2,847
  • 1
  • 17
  • 21
2

Use trailingIcon Composable property with IconButton to match the background selector of the icon with the rest of the theme. You can also put empty condition to display it only when there is some input in the text field.

Below is sample code snippet:

var text by remember { mutableStateOf ("") }

TextField(
    trailingIcon = {
        when {
            text.isNotEmpty() -> IconButton(onClick = {
                text = ""
            }) {
                Icon(
                    imageVector = Icons.Filled.Clear,
                    contentDescription = "Clear"
                )
            }
        }
    }
)
Vikas Patidar
  • 42,865
  • 22
  • 93
  • 106
0

This shall achieve this

//Caller
val text by remember { mutableStateOf (...) }

TextInput(text, ..., ...,)

//Composable
@Composable
fun TextInput(text, ..., ...){
val textState by remember { mutableStateOf (text) }
TextField(
 value = textState,
trailingIcon = {
 Icon(..., Modifier.clickable { textState = "" })
}
}

Richard Onslow Roper
  • 5,477
  • 2
  • 11
  • 42