React Native: comment sélectionner le TextInput suivant après avoir appuyé sur le bouton "next" du clavier?

j'ai défini deux champs TextInput comme suit:

<TextInput 
   style = {styles.titleInput}
   returnKeyType = {"next"}
   autoFocus = {true}
   placeholder = "Title" />
<TextInput
   style = {styles.descriptionInput}          
   multiline = {true}
   maxLength = {200}
   placeholder = "Description" />

mais après avoir appuyé sur le bouton" Suivant " de mon clavier, mon application react-native ne saute pas au deuxième champ de TextInput. Comment puis-je y parvenir?

Merci!

98
demandé sur andreaswienes 2015-09-23 23:17:51

15 réponses

définit le second TextInput focus, lorsque le précédent TextInput 's onSubmitEditing est déclenché.

Essayez cette

  1. Ajout d'une référence à deuxième TextInput

    ref={(input) => { this.secondTextInput = input; }}

  2. Lier fonction de mise au point de première TextInput 's onSubmitEditing événement.

    onSubmitEditing={() => { this.secondTextInput.focus(); }}

  3. N'oubliez pas de mettre blurOnSubmit à false, pour empêcher le clignotement du clavier.

    blurOnSubmit={false}

Quand tout est fait, il devrait ressembler à ceci.

<TextInput
    placeholder = "FirstTextInput"
    returnKeyType = { "next" }
    onSubmitEditing={() => { this.secondTextInput.focus(); }}
    blurOnSubmit={false}
/>

<TextInput
    ref={(input) => { this.secondTextInput = input; }}
    placeholder = "secondTextInput"
/>
167
répondu boredgames 2018-05-17 19:49:21

vous pouvez faire ceci sans utiliser les réfs . Cette approche est privilégiée, puisque les FRE peuvent mener au fragile code . Le React docs conseille de trouver d'autres solutions dans la mesure du possible:

si vous n'avez pas programmé plusieurs applications avec React, votre premier l'inclinaison est généralement va être d'essayer d'utiliser les références à "faire les choses produire dans votre application. Si c'est le cas, prenez une moment et pense plus critique au sujet de l'état doivent être détenus dans la composante hiérarchie. Souvent, il devient clair que l'endroit approprié pour "posséder" que l'état est à un niveau supérieur dans la hiérarchie. Placer l'etat n' souvent élimine tout désir d'utiliser des références pour "faire bouger les choses"" – au lieu de cela, le flux de données accomplira généralement votre objectif.

à la place, Nous allons utiliser une variable d'État pour focaliser le second champ d'entrée.

  1. ajouter une variable d'état que nous allons passer comme un prop à la DescriptionInput :

    initialState() {
      return {
        focusDescriptionInput: false,
      };
    }
    
  2. définir une méthode de gestionnaire qui définira cette variable d'État à true:

    handleTitleInputSubmit() {
      this.setState(focusDescriptionInput: true);
    }
    
  3. lors de la soumission / frappe enter / suivant sur le TitleInput , nous appellerons handleTitleInputSubmit . Cela mettra focusDescriptionInput à vrai.

    <TextInput 
       style = {styles.titleInput}
       returnKeyType = {"next"}
       autoFocus = {true}
       placeholder = "Title" 
       onSubmitEditing={this.handleTitleInputSubmit}
    />
    
  4. DescriptionInput 's focus prop est réglé sur notre variable d'état focusDescriptionInput . Ainsi, lorsque focusDescriptionInput change (à l'étape 3), DescriptionInput renaîtra avec focus={true} .

    <TextInput
       style = {styles.descriptionInput}          
       multiline = {true}
       maxLength = {200}
       placeholder = "Description" 
       focus={this.state.focusDescriptionInput}
    />
    

c'est une bonne façon d'éviter d'utiliser le code refs, car le code refs peut conduire à un code plus fragile:)

éditer: h/t à @ LaneRettig pour avoir souligné que vous aurez besoin d'envelopper la réaction TextInput natif avec un peu ajouté les accessoires et les méthodes pour l'obtenir à répondre à focus :

    // Props:
    static propTypes = { 
        focus: PropTypes.bool,
    } 

    static defaultProps = { 
        focus: false,
    } 

    // Methods:
    focus() {
        this._component.focus(); 
    } 

    componentWillReceiveProps(nextProps) {
        const {focus} = nextProps; 

        focus && this.focus(); 
    }
40
répondu Stedman Blake 2016-02-28 23:15:03

Que de Réagir Natif de 0,36, en appelant focus() (comme suggéré dans plusieurs autres réponses) sur un texte de nœud d'entrée n'est pas pris en charge. À la place, vous pouvez utiliser le module TextInputState de React Native. J'ai créé le module d'aide Suivant pour faciliter cela:

// TextInputManager
//
// Provides helper functions for managing the focus state of text
// inputs. This is a hack! You are supposed to be able to call
// "focus()" directly on TextInput nodes, but that doesn't seem
// to be working as of ReactNative 0.36
//
import { findNodeHandle } from 'react-native'
import TextInputState from 'react-native/lib/TextInputState'


export function focusTextInput(node) {
  try {
    TextInputState.focusTextInput(findNodeHandle(node))
  } catch(e) {
    console.log("Couldn't focus text input: ", e.message)
  }
}

vous pouvez alors appeler la fonction focusTextInput sur n'importe quelle" réf "d'un TextInput . Par exemple:

...
<TextInput onSubmit={() => focusTextInput(this.refs.inputB)} />
<TextInput ref="inputB" />
...
23
répondu Mitch 2016-11-28 04:46:35

j'ai créé une petite bibliothèque qui fait cela, aucun changement de code nécessaire autre que de remplacer votre vue d'emballage et l'importation de TextInput:

import { Form, TextInput } from 'react-native-autofocus'

export default () => (
  <Form>
    <TextInput placeholder="test" />
    <TextInput placeholder="test 2" />
  </Form>
)

https://github.com/zackify/react-native-autofocus

expliqué en détail ici: https://zach.codes/autofocus-entrées-en-réagir-natif/

15
répondu zackify 2017-08-02 19:47:45

en utilisant react-native 0.45.1 j'ai également rencontré des problèmes en essayant de mettre l'accent sur un mot de passe TextInput après avoir appuyé sur la touche return sur un nom D'utilisateur TextInput.

après avoir essayé la plupart des solutions les mieux notées ici sur donc j'ai trouvé une solution sur github qui a répondu à mes besoins: https://github.com/shoutem/ui/issues/44#issuecomment-290724642

pour résumer:

import React, { Component } from 'react';
import { TextInput as RNTextInput } from 'react-native';

export default class TextInput extends Component {
    render() {
        const { props } = this;

        return (
            <RNTextInput
                {...props}
                ref={(input) => props.inputRef && props.inputRef(input)}
            />
        );
    }
}

et ensuite je l'utilise comme ceci:

import React, {Component} from 'react';
import {
    View,
} from 'react-native';
import TextInput from "../../components/TextInput";

class Login extends Component {
    constructor(props) {
        super(props);
        this.passTextInput = null
    }

    render() {
        return (
            <View style={{flex:1}}>
                <TextInput
                    style={{flex:1}}
                    placeholder="Username"
                    onSubmitEditing={(event) => {
                        this.passTextInput.focus()
                    }}
                />

                <TextInput
                    style={{flex:1}}
                    placeholder="Password"
                    inputRef={(input) => {
                        this.passTextInput = input
                    }}
                />
            </View>
        )
    }
}
10
répondu kuhr 2017-07-22 09:51:02

si vous utilisez tcomb-form-native comme je suis, vous pouvez le faire, aussi. Voici l'astuce: au lieu de régler les accessoires du TextInput directement, vous le faites via options . Vous pouvez vous référer aux champs du formulaire comme:

this.refs.form.getComponent('password').refs.input.focus()

donc le produit final ressemble à quelque chose comme ceci:

var t = require('tcomb-form-native');
var Form = t.form.Form;

var MyForm = t.struct({
  field1:     t.String,
  field2:     t.String,
});

var MyComponent = React.createClass({

  _getFormOptions () {
    return {
      fields: {
        field1: {
          returnKeyType: 'next',
          onSubmitEditing: () => {this.refs.form.getComponent('field2').refs.input.focus()},
        },
      },
    };
  },

  render () {

    var formOptions = this._getFormOptions();

    return (
      <View style={styles.container}>
        <Form ref="form" type={MyForm} options={formOptions}/>
      </View>
    );
  },
});

(crédit à remcoanker pour poster l'idée ici: https://github.com/gcanti/tcomb-form-native/issues/96 )

7
répondu Lane Rettig 2016-02-05 00:24:52

pour moi sur RN 0.50.3 c'est possible de cette façon:

<TextInput 
  autoFocus={true} 
  onSubmitEditing={() => {this.PasswordInputRef._root.focus()}} 
/>

<TextInput ref={input => {this.PasswordInputRef = input}} />

vous devez voir ça.PasswordInputRef. _root .focus()

6
répondu Dmitry 2018-04-30 01:21:23

essayez cette solution sur les problèmes de GitHub de React Native.

https://github.com/facebook/react-native/pull/2149#issuecomment-129262565

vous devez utiliser la prop ref pour le composant TextInput.

Ensuite, vous avez besoin d'une création d'une fonction qui est appelée onSubmitEditing prop qui déplace le focus sur le second TextInput ref.

var InputScreen = React.createClass({
    _focusNextField(nextField) {
        this.refs[nextField].focus()
    },

    render: function() {
        return (
            <View style={styles.container}>
                <TextInput
                    ref='1'
                    style={styles.input}
                    placeholder='Normal'
                    returnKeyType='next'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('2')}
                />
                <TextInput
                    ref='2'
                    style={styles.input}
                    keyboardType='email-address'
                    placeholder='Email Address'
                    returnKeyType='next'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('3')}
                />
                <TextInput
                    ref='3'
                    style={styles.input}
                    keyboardType='url'
                    placeholder='URL'
                    returnKeyType='next'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('4')}
                />
                <TextInput
                    ref='4'
                    style={styles.input}
                    keyboardType='numeric'
                    placeholder='Numeric'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('5')}
                />
                <TextInput
                    ref='5'
                    style={styles.input}
                    keyboardType='numbers-and-punctuation'
                    placeholder='Numbers & Punctuation'
                    returnKeyType='done'
                />
            </View>
        );
    }
});
3
répondu APAquino 2015-09-24 22:38:05

utilisant des références de rappel au lieu du legacy string refs:

<TextInput
    style = {styles.titleInput}
    returnKeyType = {"next"}
    autoFocus = {true}
    placeholder = "Title"
    onSubmitEditing={() => {this.nextInput.focus()}}
/>
<TextInput
    style = {styles.descriptionInput}  
    multiline = {true}
    maxLength = {200}
    placeholder = "Description"
    ref={nextInput => this.nextInput = nextInput}
/>
3
répondu fagerbua 2016-11-11 12:17:24

pour que la solution acceptée fonctionne si votre TextInput se trouve à l'intérieur d'un autre composant, vous devez" pop "la référence de ref au conteneur parent.

// MyComponent
render() {
    <View>
        <TextInput ref={(r) => this.props.onRef(r)} { ...this.props }/>
    </View>
}

// MyView
render() {
    <MyComponent onSubmitEditing={(evt) => this.myField2.focus()}/>
    <MyComponent onRef={(r) => this.myField2 = r}/>
}
2
répondu Eldelshell 2016-12-17 18:48:02

C'est comme ça que j'y suis arrivé. Et l'exemple ci-dessous a utilisé la Réaction.API createRef () introduite dans React 16.3.

class Test extends React.Component {
  constructor(props) {
    super(props);
    this.secondTextInputRef = React.createRef();
  }

  render() {
    return(
        <View>
            <TextInput
                placeholder = "FirstTextInput"
                returnKeyType="next"
                onSubmitEditing={() => { this.secondTextInputRef.current.focus(); }}
            />
            <TextInput
                ref={this.secondTextInputRef}
                placeholder = "secondTextInput"
            />
        </View>
    );
  }
}

je pense que cela vous aidera.

2
répondu Janaka Pushpakumara 2018-07-10 09:53:02

il y a un moyen de capturer tabs dans un TextInput . C'est hacky, mais mieux que rien .

définit un handler onChangeText qui compare la nouvelle valeur d'entrée avec l'ancienne, en vérifiant pour un \t . Si on en trouve un, avancez le champ comme indiqué par @boredgames

suppose que la variable username contient la valeur du nom d'utilisateur et setUsername envoie une action à changement dans le magasin (état des composants, redux magasin, etc), faire quelque chose comme ceci:

function tabGuard (newValue, oldValue, callback, nextCallback) {
  if (newValue.indexOf('\t') >= 0 && oldValue.indexOf('\t') === -1) {
    callback(oldValue)
    nextCallback()
  } else {
    callback(newValue)
  }
}

class LoginScene {
  focusNextField = (nextField) => {
    this.refs[nextField].focus()
  }

  focusOnPassword = () => {
    this.focusNextField('password')
  }

  handleUsernameChange = (newValue) => {
    const { username } = this.props            // or from wherever
    const { setUsername } = this.props.actions // or from wherever

    tabGuard(newValue, username, setUsername, this.focusOnPassword)
  }

  render () {
    const { username } = this.props

    return (
      <TextInput ref='username'
                 placeholder='Username'
                 autoCapitalize='none'
                 autoCorrect={false}
                 autoFocus
                 keyboardType='email-address'
                 onChangeText={handleUsernameChange}
                 blurOnSubmit={false}
                 onSubmitEditing={focusOnPassword}
                 value={username} />
    )
  }
}
1
répondu marius 2016-09-06 08:23:15

dans votre composant:

constructor(props) {
        super(props);
        this.focusNextField = this
            .focusNextField
            .bind(this);
        // to store our input refs
        this.inputs = {};
    }
    focusNextField(id) {
        console.log("focus next input: " + id);
        this
            .inputs[id]
            ._root
            .focus();
    }

Note: j'ai utilisé ._root parce que c'est un ref à TextInput dans NativeBase "Library" Input

et dans vos entrées de texte comme ceci

<TextInput
         onSubmitEditing={() => {
                          this.focusNextField('two');
                          }}
         returnKeyType="next"
         blurOnSubmit={false}/>


<TextInput      
         ref={input => {
              this.inputs['two'] = input;
                        }}/>
1
répondu amorenew 2017-10-03 10:57:30

Mon scénario est < CustomBoladonesTextInput /> l'enveloppant d'un RN < TextInput /> .

j'ai résolu cette question comme suit:

mon formulaire ressemble à:

  <CustomBoladonesTextInput 
      onSubmitEditing={() => this.customInput2.refs.innerTextInput2.focus()}
      returnKeyType="next"
      ... />

  <CustomBoladonesTextInput 
       ref={ref => this.customInput2 = ref}
       refInner="innerTextInput2"
       ... />

sur la définition de Component de CustomBoladonesTextInput, je passe le champ de refField à l'intérieur ref prop comme ceci:

   export default class CustomBoladonesTextInput extends React.Component {
      render() {        
         return (< TextInput ref={this.props.refInner} ... />);     
      } 
   }

et voilà. Tout revenir fonctionne à nouveau. Espérons que cette aide

1
répondu Rodrigo Tessarollo 2018-01-16 03:34:50

Voici une solution de réactif pour un composant d'entrée qui a une propriété: focus.

le champ sera focalisé aussi longtemps que cet accessoire est mis à vrai et n'aura pas de focalisation aussi longtemps que ce est faux.

malheureusement ce composant doit avoir un: ref défini, Je n'ai pas pu trouver un autre moyen d'appeler .focus() sur celui-ci. Je suis heureux de suggestions.

(defn focusable-input [init-attrs]
  (r/create-class
    {:display-name "focusable-input"
     :component-will-receive-props
       (fn [this new-argv]
         (let [ref-c (aget this "refs" (:ref init-attrs))
               focus (:focus (ru/extract-props new-argv))
               is-focused (.isFocused ref-c)]
           (if focus
             (when-not is-focused (.focus ref-c))
             (when is-focused (.blur ref-c)))))
     :reagent-render
       (fn [attrs]
         (let [init-focus (:focus init-attrs)
               auto-focus (or (:auto-focus attrs) init-focus)
               attrs (assoc attrs :auto-focus auto-focus)]
           [input attrs]))}))

https://gist.github.com/Knotschi/6f97efe89681ac149113ddec4c396cc5

0
répondu Knotschi 2016-04-15 17:48:47