When you create an application, you need to manage the keyboard and in theory, the principle is quite simple. When you press an input, the keyboard opens and when you press outside the input the keyboard closes. But this behavior is not trivial in React-Native and you will have to handle it by yourself.
I will distinguish between two types of screens here, screens wrapped with a
and a View
ScrollView
.
If your screen is wrapped with a
, you can see below that the keyboard does not close automatically when you press outside your input.View
If your screen is wrapped with a ScrollView
, we have 3 different behaviors depending on the prop
and according to keyboardShouldPersistTaps
documentation :ScrollView
What is missing here? It is impossible to handle button press and dismiss the keyboard with a single click. With
, need one press to dismiss the keyboard and another to handle the button. With never
, we simply cannot close the keyboard and with always
, pressing the button does not dismiss the keyboard.handled
I first checked on the internet to see what the current solutions were and I found this : Wrapping your application with a Pressable that dismisses the keyboard. The
that dismiss the keyboard. The Pressable
is here to avoir breaking accessibility, you can check this article if you want to learn more.accessible={false}
This is very simple but is equivalent to the
of the keyboardShouldPersistTaps="handled"
, when we press a child button the keyboard is not dismissed and this can lead to bugs.Scrollview
For example, if you want to open a
when you click on a button by using BottomSheet
of presentation: "transparentModal"
. You will have the following behavior on Android.react-navigation
This is how it works:
Here we use react-native-gesture-handler to detect the tap and dismiss the keyboard even if a child (e.g. a button) catches it. Dismissing the keyboard at the end of the tap ensures that scrolling still works with the keyboard open. We also ensure that the keyboard is not dismissed when a
is pressed with a solution inspired by TextInput
’s code using Scrollview
. When a isTextInput(e.target)
is mounted, it reference is added to a TextInput
and Set
simply checks if the inputs isTextInput
contains the target.Set
⚠️ Warning
GestureHandlerRootView
KeyboardDismissPressable
instead of wrapping the whole application to avoid some conflicts and to be more flexible if some pages need a different behavior.
TextInputState
because this state is not exposed by react-native. So this internal function may be changed in future versions of react-native.I am open to your challenges or ideas to improve this component so feel free to contact me if you would like to discuss this topic.