In my app, I have a TextField
and a button which should show/hide the IME keyboard. I have read all about controlling the soft keyboard and how to show or hide it, but not how to toggle. This SO post is related, but not exactly what I'm asking for.
The problem I have is that I need to keep track of when the keyboard has been opened and closed. It's possible to open the keyboard by tapping on the TextField
of course, and it's possible to close it by pressing the back button. I can't find any hooks or callbacks for those actions, so I can assign isKeyboardOpen
boolean.
Because of that, I can toggle the keyboard from the Toggle keyboard!
button, but as soon as I "manually" open it (tap on the text field) or close it (press the back button), the toggle button state can't be updated and I need to press it twice for it to show/hide the keyboard.
So far I had tried the following:
BackHandler
- no effectModifier.pointerInput(Unit)
withdetectTapGestures
- those callbacks are never hit on tapping theTextField
onKeyEvent
andonPreviewKeyEvent
- they seem to be for hardware keyboard key presses only. I tried to intercept the back press, as we'd done it in the Android Views world:action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK
, but no luck
Here's the code for those two elements, as illustrated in the gif below:
Surface {
var isKeyboardOpen by remember { mutableStateOf(false) }
val keyboardController = LocalSoftwareKeyboardController.current
Column {
Button(onClick = {
isKeyboardOpen = !isKeyboardOpen
if (isKeyboardOpen) keyboardController?.show() else keyboardController?.hide()
}
) {
Text("Toggle keyboard!")
}
//...
BackHandler(isKeyboardOpen) {
Log.d("TextField", "backPressed - never called")
}
var text by remember { mutableStateOf("") }
TextField(
value = text,
onValueChange = { text = it },
modifier = Modifier.pointerInput(Unit) {
detectTapGestures(
onTap = { Log.d("TextField", "onTap - never called") },
onPress = { Log.d("TextField", "onPress - never called") },
)
}.onKeyEvent { event ->
// callback never hit
if (event.type == KeyEventType.KeyUp && event.key == Key.Back) {
//....
}
true
}
)
}
}
Gif of trying to toggle keyboard open/closed from a button
How can I implement keyboard toggle button in compose? Is it even possible?
CodePudding user response:
You can use WindowInsets to detect whether keyboard is open or close.
Follow these instructions to add and setup Accompanist Insets Library.
Once set up you can create you button like this.
val insets = LocalWindowInsets.current
val keyboardController = LocalSoftwareKeyboardController.current
Button(onClick = {
if (insets.ime.isVisible) keyboardController?.hide() else keyboardController?.show()
}) {
Text("Toggle keyboard!")
}
CodePudding user response:
You can use the KeyboardVisibilityEvent library for that
KeyboardVisibilityEvent.setEventListener(
getActivity(),
new KeyboardVisibilityEventListener() {
@Override
public void onVisibilityChanged(boolean isOpen) {
// do your thing here !!
}
});