Keyboard does not hide, when focused TextField leaves the LazyColumn

Viewed 613

Perhaps this is the normal behaviour, but i wish it was different. I had tried to google the solution, but did not find anything suitable (or merely missed it).

Sample code (for simplicity i hold mutable states right here, not using ViewModel):

@Composable
fun Greeting() {
    Scaffold(topBar = {
        TopAppBar(title = { Text(text = "Some title") })
    }) {
        val focusManager = LocalFocusManager.current
        LazyColumn(
            contentPadding = PaddingValues(all = 16.dp),
            verticalArrangement = Arrangement.spacedBy(space = 16.dp)
        ) {
            items(count = 20) { index ->
                val (value, onValueChange) = rememberSaveable { mutableStateOf("Some value $index") }
                TextField(
                    value = value,
                    onValueChange = onValueChange,
                    modifier = Modifier.fillMaxWidth(),
                    label = { Text(text = "Some label $index") },
                    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
                    keyboardActions = KeyboardActions(onNext = {
                        if (!focusManager.moveFocus(FocusDirection.Down))
                            focusManager.clearFocus()
                    }),
                    singleLine = true
                )
            }
        }
    }
}

Compose version 1.0.5

1 Answers

You could try just hiding the keyboard whenever scrolling occurs. This is okay as long as you don't have a large set of items. But since you're using TextFields, it isn't likely that you'll have such a large number. This sample illustrates hiding the keyboard when scrolling occurs:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        startActivity(intent)

        setContent {
            Greeting(this)
        }
    }
}

@Composable
fun Greeting(activity: Activity) {

    Scaffold(topBar = {
        TopAppBar(title = { Text(text = "Some title") })
    }) {

        val lazyListState = rememberLazyListState()
        val ctx = LocalContext.current

        LaunchedEffect(lazyListState.firstVisibleItemIndex) {
            val inputMethodManager = ctx.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            inputMethodManager.hideSoftInputFromWindow(activity.window?.decorView?.windowToken, 0)
        }

        LazyColumn(
            state = lazyListState,
            contentPadding = PaddingValues(all = 16.dp),
            verticalArrangement = Arrangement.spacedBy(space = 16.dp)
        ) {
            items(
                count = 20,
                key = { index ->
                    // Return a stable + unique key for the item
                    index
                }
            ) { index ->
                val (value, onValueChange) = rememberSaveable { mutableStateOf("Some value $index") }
                TextField(
                    value = value,
                    onValueChange = onValueChange,
                    modifier = Modifier
                        .fillMaxWidth(),
                    label = { Text(text = "Some label $index") },
                    singleLine = true
                )
            }
        }
    }
}
Related