Comment ignorer le clavier avec react-navigation dans les applications React Native

Afficher et ignorer le clavier peut sembler une tâche banale dans les applications mobiles, mais il peut être difficile de le supprimer automatiquement lorsqu'il est associé à une navigation modale et à une présentation modale. Du moins, cela est conforme à mon hypothèse initiale. Cet article a pour but de détailler ce que j'ai appris sur la gestion du clavier et comment éviter de toucher davantage lorsque vous utilisez TextInput. Il y aura également beaucoup de spéléologie de code, grâce à toutes les bibliothèques ouvertes. La version de React Native que j’utilise au moment de la rédaction est 0.57.5.

Le composant TextInput intégré

React Native est livré avec un ensemble de composants de base, dont le TextInput pour la saisie de texte dans l'application via un clavier.

importer Réagir, {Composant} de 'réagir';
importer {AppRegistry, TextInput} de 'react-native';
La classe d'export par défaut, UselessTextInput, étend le composant {
  constructeur (accessoires) {
    super (accessoires);
    this.state = {text: 'Placeholder inutile'};
  }
render () {
    revenir (
       this.setState ({text})}
        valeur = {this.state.text}
      />
    )
  }
}

C’est tout, chaque fois que nous cliquons sur la saisie de texte, un clavier apparaît nous permettant de saisir des valeurs. Pour désactiver le clavier en appuyant n’importe où sur l’écran, la solution simple consiste à TouchableWithoutFeedback avec Keyboard. Ceci est similaire à avoir UITapGestureRecognizer dans iOS UIView et à appeler view.endEditing

importer {clavier} de 'react-native'

Clavier.dismiss ()

TextInput dans ScrollView

Normalement, nous devrions avoir quelques entrées de texte dans un composant de défilement. Dans React Native, il s'agit principalement de ScrollView pour pouvoir gérer une longue liste de contenu et éviter le clavier. Si TextInput est dans ScrollView, la manière dont le clavier est masqué se comporte un peu différemment et dépend de keyboardShouldPersistTaps.

Détermine quand le clavier doit rester visible après un tapotement.

  • 'jamais' (par défaut), si vous tapez en dehors de la saisie de texte sélectionnée lorsque le clavier est activé, le clavier est masqué. Lorsque cela se produit, les enfants ne reçoivent pas le robinet.
  • 'toujours', le clavier ne sera pas automatiquement désactivé et la vue de défilement ne capturera pas les taps, mais les enfants de la vue de défilement pourront capturer les taps.
  • 'manipulé', le clavier ne disparaîtra pas automatiquement lorsque le tapotement a été manipulé par un enfant (ou capturé par un ancêtre).

Le mode Jamais devrait être le comportement souhaité dans la plupart des cas, un clic en dehors de la saisie de texte ciblée devrait faire fuir le clavier.

Dans mon application, il y a quelques entrées de texte et un bouton d'action. Le scénario est que les utilisateurs entrent des informations puis appuient sur ce bouton pour enregistrer des données. Avec le mode Never, nous devons appuyer sur le bouton deux fois, un pour quitter le clavier et deux pour appuyer sur le bouton. La solution consiste donc à toujours utiliser le mode. De cette façon, le bouton obtient toujours l'événement de presse en premier.

ScrollView se soucie du clavier

La classe native RCTScrollView qui fait réagir ScrollView natif a du code pour gérer le mode de renvoi.

RCT_SET_AND_PRESERVE_OFFSET (setKeyboardDismissMode, keyboardDismissMode, UIScrollViewKeyboardDismissMode)

L'option choisie est la propriété UIScrollViewKeyboardDismissMode pour la propriété keyboardDismissMode.

La manière dont le clavier est ignoré lorsqu'un glisser commence dans la vue de défilement.

Comme vous pouvez le constater, les modes possibles sont onDrag et interactif. Et réagissez natif expose le point de personnalisation pour cela via keyboardShouldPersistTaps

case none Le clavier n'est pas masqué par un glisser.

case onDrag Le clavier est désactivé quand un glissement commence.

case interactive Le clavier suit le glisser-déposer hors écran et peut être tiré à nouveau vers le haut pour annuler la suppression.

ScrollView à l'intérieur d'un modal

Mais cela ne fonctionne pas lorsque ScrollView est dans Modal. Par modal, j'entendais le composant modal dans React Native. La seule bibliothèque que j'utilise est react-navigation, et elle supporte aussi l'ouverture d'un modal en plein écran, mais la façon dont nous déclarons modal dans react-navigation ressemble à de la pile et c'est déroutant, alors je préférerais ne pas l'utiliser. J'utilise Modal dans react-native et cela fonctionne plutôt bien.

Donc, si nous avons TextInput dans ScrollView dans Modal, keyboardShouldPersistTaps ne fonctionne pas. Modal semble être au courant de ScrollView parent. Nous devons donc déclarer keyboardShouldPersistTaps = 'toujours' sur chaque ScrollView parent. Dans React, Native FlatList et SectionList utilisent ScrollView sous le capot. Nous devons donc connaître tous ces composants ScrollView.

Spéléologie réact-navigation

Étant donné que mon application repose beaucoup sur la navigation par réaction, il est bon d’avoir une compréhension approfondie de ses composants afin que nous puissions savoir où est le problème. J'ai écrit un peu sur la structure de réaction-navigation ci-dessous.

Comme toutes les applications mobiles traditionnelles, mon application se compose de nombreux navigateurs de pile à l'intérieur du navigateur d'onglets. Dans iOS, cela signifie de nombreux UINavigationViewController dans UITabbarController. Dans react-navigation j'utilise createMaterialTopTabNavigator dans createBottomTabNavigator

importer {createMaterialTopTabNavigator} à partir de 'react-navigation'
importer {createBottomTabNavigator, BottomTabBar} à partir de 'react-navigation-tabs'

L’écran que j’ai avec le clavier est un modal présenté à partir du deuxième écran dans l’un des navigateurs de la pile. Nous allons donc examiner chaque vue de défilement possible dans la hiérarchie. Ce processus implique beaucoup de lecture de code et c’est ce que j’adore l’open source.

Commençons d’abord par createBottomTabNavigator, qui utilise createTabNavigator avec son propre TabNavigationView.

la classe TabNavigationView étend React.PureComponent 
exporter par défaut createTabNavigator (TabNavigationView);

Le navigateur d'onglets a une vue de la barre d'onglets sous ScreenContainer, utilisée pour contenir la vue. ScreenContainer est issu des écrans react-native-native «Ce projet vise à exposer les composants de conteneur de navigation natifs à React Native». Vous trouverez ci-dessous le fonctionnement du navigateur d'onglets.

render () {
  const {navigation, renderScene, lazy} = this.props;
  const {routes} = navigation.state;
  const {chargé} = this.state
  revenir (