Keyboard issues in ScrollView
When we use TextInput to enter text the keyboard pops up and occupies a bit of space on the screen.
When we use TextInput inside a scrollable page there are a couple of issues i mostly ran into with the keyboard being in focus. Common use-cases are forms, messaging applications, free text boxes, etc.. where we use a TextInput component inside a ScrollView.
Problem 1: Button needs to be tapped twice
The most common and irritating thing is when the keyboard is up, tapping anywhere else on the screen will require you to do it twice. The first time you tap anywhere outside the TextInput, it dismisses the keyboard. Once the keyboard is dismissed the second tap enables the action.
This can be seen in the example below.
Luckily, React Native team has a fix for this.
Fix: keyboardShouldPersistTaps
The keyboardShouldPersistTaps property can be set in the ScrollView component.
This property fixes the double tap issue and ensures that the keyboard doesn’t come in your way of tapping elsewhere on the screen.
<ScrollView keyboardShouldPersistTaps='always'>
<Item>
<Input
onChangeText={(value) => this.formState.$.code1.onChange(value)}
placeholder='Code'
style={styles.inputCtrl}
keyboardType='numeric'
autoCapitalize='none'
blurOnSubmit={false}
/>
</Item>
<Item>
<Input
onChangeText={(value) => this.formState.$.code2.onChange(value)}
placeholder='Code'
style={styles.inputCtrl}
keyboardType='numeric'
autoCapitalize='none'
blurOnSubmit={false}
/>
</Item>
<Button style={styles.btn} onPress={() => this.submitForm()}>
<Text style={styles.btnText}>Submit</Text>
</Button>
</ScrollView>
after the fix it works as follows:
In the above example, the keyboardShouldPersistTaps is set to 'always'. It ensures that the keyboard will not dismiss automatically, and the scroll view will not catch taps, but children of the ScrollView can catch taps.
The property can also be set to other values, depending on the use-case of your app:
-
never
(default): tapping outside of the focused text input when the keyboard is up dismisses the keyboard. When this happens, children won't receive the tap. -
handled
: the keyboard will not dismiss automatically when the tap was handled by a children.
Problem 2: Keyboard does not dismiss while scrolling through the page.
Another common issue I have came across is the keyboard would be up while scrolling through a page, unless we tap outside the TextInput and dismiss it.
Tapping and dismissing it is not the ideal solution for a seamless experience.
Fix: keyboardDismissMode
The keyboardDismissMode property can be set inside the ScrollView.
Setting it to on-drag, ensures that the keyboard is dismissed when a drag begins.
<ScrollView keyboardDismissMode='on-drag'>
<Item>
<Input
onChangeText={(value) => this.formState.$.code1.onChange(value)}
placeholder='Code'
style={styles.inputCtrl}
keyboardType='numeric'
autoCapitalize='none'
blurOnSubmit={false}
/>
</Item>
<Item>
<Input
onChangeText={(value) => this.formState.$.code2.onChange(value)}
placeholder='Code'
style={styles.inputCtrl}
keyboardType='numeric'
autoCapitalize='none'
blurOnSubmit={false}
/>
</Item>
<Button style={styles.btn} onPress={() => this.submitForm()}>
<Text style={styles.btnText}>Submit</Text>
</Button>
</ScrollView>
after the fix it works as follows:
For iOS devices this property can be set to interactive. It ensures the keyboard is dismissed interactively with the drag and moves in synchrony with the touch; dragging upwards cancels the dismissal.