4

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?

jesobremonte
  • 3,198
  • 2
  • 22
  • 30

1 Answers1

4

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 = ""
            }
        }
    )
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • Thanks, I've decided to use this workaround for now, but using a boolean instead of a string key. Though it does seem like a bug that onFocusChanged is being called upon creation of the compose TextField. – jesobremonte Oct 02 '22 at 09:11