Search code examples
androidandroid-jetpack-composeandroid-compose-textfield

Compose TextField Modifier.onFocusChanged {} event being called upon initialization even though no user focus interactions have been done


Reproducible with code:

var value by remember { mutableStateOf("Hello\nWorld\nInvisible") }

TextField(
    value = value,
    onValueChange = { value = it },
    label = { Text("Enter text") },
    modifier = Modifier
        .onFocusChanged { Log.d("TAG", "1 OnFocusChangedCalled: $it") }
)

TextField(
    value = value,
    onValueChange = { value = it },
    label = { Text("Enter text") },
    modifier = Modifier
        .onFocusChanged { Log.d("TAG", "2 OnFocusChangedCalled: $it") }
)

Upon simply opening the view, Logcat shows:

D/TAG: 1 OnFocusChangedCalled: Inactive
D/TAG: 2 OnFocusChangedCalled: Inactive

With traditional XML layouts, onFocusChangedListener only triggers when user actually interacts with the field.

With compose layout, I'm trying to do error validation only when user removes focus from a TextField.

However this behaviour is causing my validation to trigger as soon as the view is initialized.

How can I make the onFocusChanged validation only occur after the user removes focus from the field, instead of upon initialization?


Solution

  • You can move the validation in the onValueChange attribute instead of the onFocusChanged modifier.

    As workaround you can store a key when the a field gains the focus and then check this value when the focus is lost.

    Something like:

     var focusedTextKey by remember { mutableStateOf("") }
    
     TextField(
        value = value,
        onValueChange = { value = it },
        label = { Text("Enter text") },
        modifier = Modifier
            .onFocusChanged {
                Log.d("TAG", "1 OnFocusChangedCalled: $it")
    
                if (it.isFocused) {
                    focusedTextKey = "NAME"
                } else {
                    if (focusedTextKey == "NAME") {
                        //validate the value
                    }
                    focusedTextKey = ""
                }
            }
        )