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!
15 réponses
définit le second TextInput
focus, lorsque le précédent TextInput
's onSubmitEditing
est déclenché.
Essayez cette
-
Ajout d'une référence à deuxième TextInput
ref={(input) => { this.secondTextInput = input; }}
-
Lier fonction de mise au point de première TextInput 's onSubmitEditing événement.
onSubmitEditing={() => { this.secondTextInput.focus(); }}
-
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"
/>
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.
-
ajouter une variable d'état que nous allons passer comme un prop à la
DescriptionInput
:initialState() { return { focusDescriptionInput: false, }; }
-
définir une méthode de gestionnaire qui définira cette variable d'État à true:
handleTitleInputSubmit() { this.setState(focusDescriptionInput: true); }
-
lors de la soumission / frappe enter / suivant sur le
TitleInput
, nous appelleronshandleTitleInputSubmit
. Cela mettrafocusDescriptionInput
à vrai.<TextInput style = {styles.titleInput} returnKeyType = {"next"} autoFocus = {true} placeholder = "Title" onSubmitEditing={this.handleTitleInputSubmit} />
-
DescriptionInput
'sfocus
prop est réglé sur notre variable d'étatfocusDescriptionInput
. Ainsi, lorsquefocusDescriptionInput
change (à l'étape 3),DescriptionInput
renaîtra avecfocus={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();
}
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" />
...
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/
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>
)
}
}
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 )
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()
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>
);
}
});
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}
/>
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}/>
}
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.
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} />
)
}
}
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;
}}/>
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
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