Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent TextInput to focus while scrolling on iOS

I have a ScrollView with a TextInput multiline={true} field which serves as a text area with dynamic height, and content read from state (it has a Text field inside which displays the text).

My problem is that when the TextInput grows to a couple of lines, if I scroll the screen by swiping over this field (I don't long press or anything like that), the field will fire its onFocus event and the keyboard will show.

It doesn't happen every time but it happens enough times to make it super annoying.

I tried setting ScrollView to keyboardDismissMode="on-drag" but it doesn't help, the keyboard still shows while the view is scrolling.

<ScrollView keyboardDismissMode="on-drag">
  <TextInput multiline={true} onFocus={() => console.log('boop')}>
    <Text>{this.state.someText}</Text>
  </TextInput>
</ScrollView>

I also tried doing it without the Text field inside TextInput and onFocus still fires up.

Am I doing something wrong? Is there anything else I could try, like checking if the screen is still scrolling and blur() the field if true or something like that?

Is there any way I can only focus the field if I 'explicitly' tap on it?

Thanks for your help.

like image 517
rudikovac Avatar asked Aug 11 '16 00:08

rudikovac


1 Answers

Here's a hacky workaround:

Wrap your TextInput in a TouchableOpacity, and set the TextInput's pointerEvents prop to point to a state variable, i.e. this.state.pointerEvents, and initialize the variable to 'none'. This stops the TextInput from receiving any touch events, and lets you swipe over the top of it without capturing focus.

In the onPress prop of the TouchableOpacity, enable the pointerEvents by setting your state variable to 'auto' and then manually assign focus using a reference to your TextInput, i.e:

this._textInput.focus()

Finally, override the onBlur prop of your TextInput and have it reinitialise the pointerEvents state back to 'none' so it behaves just like before after the user has finished editing.

Explanation

The way this works is that the TouchableOpacity essentially captures all of the touch events that would normally be consumed by the TextInput, but interacts with drags along the rest of your UI in the friendly way we'd expect it to. When the onPress event is fired for the TouchableOpacity, we really are talking about a genuine press event, and not a misrecognised drag.

If you'd prefer not to use TouchableOpacity's animation, you can assign the activeOpacity prop to 1, or use a TouchableWithoutFeedback instead.

like image 193
Mapsy Avatar answered Oct 12 '22 22:10

Mapsy