new - react native run ios
React Native: ¿Cómo seleccionar la siguiente entrada de texto después de presionar el botón de teclado "siguiente"? (17)
A partir de React Native 0.36, ya no se admite llamar a
focus()
(como se sugiere en varias otras respuestas) en un nodo de entrada de texto.
En su lugar, puede usar el módulo
TextInputState
de React Native.
Creé el siguiente módulo auxiliar para facilitar esto:
// 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)
}
}
Entonces, puede llamar a la función
focusTextInput
en cualquier "referencia" de un
TextInput
.
Por ejemplo:
...
<TextInput onSubmit={() => focusTextInput(this.refs.inputB)} />
<TextInput ref="inputB" />
...
Definí dos campos TextInput de la siguiente manera:
<TextInput
style = {styles.titleInput}
returnKeyType = {"next"}
autoFocus = {true}
placeholder = "Title" />
<TextInput
style = {styles.descriptionInput}
multiline = {true}
maxLength = {200}
placeholder = "Description" />
Pero después de presionar el botón "siguiente" en mi teclado, mi aplicación nativa de reacción no salta al segundo campo TextInput. ¿Cómo puedo lograr eso?
¡Gracias!
Aquí una solución de reactivo para un componente de entrada que tiene una propiedad: focus.
El campo se enfocará mientras este accesorio esté establecido en verdadero y no tendrá foco mientras sea falso.
Desafortunadamente, este componente necesita tener un: ref definido, no pude encontrar otra forma de llamar a .focus () en él. Estoy contento con las sugerencias.
(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
Así es como lo logré. Y el siguiente ejemplo ha utilizado la API React.createRef () presentada en 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>
);
}
}
Creo que esto te ayudará.
Creé una pequeña biblioteca que hace esto, no se necesita ningún cambio de código que no sea reemplazar su vista de ajuste e importar 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
Explicado en detalle aquí: https://zach.codes/autofocus-inputs-in-react-native/
Establezca el segundo foco
TextInput
, cuando se activa
onSubmitEditing
TextInput
anterior.
Prueba esto
-
Agregar una referencia a la segunda entrada de texto
ref={(input) => { this.secondTextInput = input; }}
-
Enlace la función de enfoque al primer evento onSubmitEditing de TextInput .
onSubmitEditing={() => { this.secondTextInput.focus(); }}
-
Recuerde establecer blurOnSubmit en false, para evitar el parpadeo del teclado.
blurOnSubmit={false}
Cuando todo esté listo, debería verse así.
<TextInput
placeholder = "FirstTextInput"
returnKeyType = { "next" }
onSubmitEditing={() => { this.secondTextInput.focus(); }}
blurOnSubmit={false}
/>
<TextInput
ref={(input) => { this.secondTextInput = input; }}
placeholder = "secondTextInput"
/>
Hay una manera de capturar
pestañas
en un
TextInput
.
Es hacky, pero mejor que
nothing
.
Defina un controlador
onChangeText
que compare el nuevo valor de entrada con el antiguo, buscando un
/t
.
Si encuentra uno, avance el campo como se muestra en @boredgames
Suponiendo que el
username
variable contiene el valor para el nombre de usuario y
setUsername
envía una acción para cambiarlo en la tienda (estado del componente, tienda redux, etc.), haga algo como esto:
<TextInput
onSubmitEditing={() => {
this.focusNextField(''two'');
}}
returnKeyType="next"
blurOnSubmit={false}/>
<TextInput
ref={input => {
this.inputs[''two''] = input;
}}/>
Mi escenario es <CustomBoladonesTextInput /> envolviendo un RN <TextInput /> .
Resolví este problema de la siguiente manera:
Mi forma se ve así:
<CustomBoladonesTextInput
onSubmitEditing={() => this.customInput2.refs.innerTextInput2.focus()}
returnKeyType="next"
... />
<CustomBoladonesTextInput
ref={ref => this.customInput2 = ref}
refInner="innerTextInput2"
... />
En la definición del componente CustomBoladonesTextInput, paso el refField al accesorio de referencia interno de esta manera:
export default class CustomBoladonesTextInput extends React.Component {
render() {
return (< TextInput ref={this.props.refInner} ... />);
}
}
Y voilá. Todo vuelve a funcionar de nuevo. Espero que esto ayude
Para mí en RN 0.50.3 es posible de esta manera:
<TextInput
autoFocus={true}
onSubmitEditing={() => {this.PasswordInputRef._root.focus()}}
/>
<TextInput ref={input => {this.PasswordInputRef = input}} />
Debes ver esto.PasswordInputRef. _root .focus ()
Para que la solución aceptada funcione si su
TextInput
está dentro de otro componente, deberá "hacer estallar" la referencia de
ref
al contenedor principal.
// 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}/>
}
Pruebe esta solución en los problemas de GitHub de React Native.
https://github.com/facebook/react-native/pull/2149#issuecomment-129262565
Debe usar el accesorio de referencia para el componente TextInput.
Luego, necesita crear una función que se llame a onSubmitEditing prop que mueva el foco en la segunda referencia TextInput.
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>
);
}
});
Puedes hacer esto sin usar referencias . Se prefiere este enfoque, ya que las referencias pueden conducir a un código frágil . Los documentos de React aconsejan encontrar otras soluciones cuando sea posible:
Si no ha programado varias aplicaciones con React, su primera inclinación será tratar de usar referencias para "hacer que las cosas sucedan" en su aplicación. Si este es el caso, tómese un momento y piense más críticamente sobre dónde debe pertenecer el estado en la jerarquía de componentes. A menudo, queda claro que el lugar adecuado para "poseer" ese estado está en un nivel superior en la jerarquía. Colocar el estado allí a menudo elimina cualquier deseo de usar referencias para "hacer que las cosas sucedan"; en cambio, el flujo de datos generalmente logrará su objetivo.
En su lugar, utilizaremos una variable de estado para enfocar el segundo campo de entrada.
-
Agregue una variable de estado que pasaremos como accesorio a la
DescriptionInput
:initialState() { return { focusDescriptionInput: false, }; }
-
Defina un método de controlador que establezca esta variable de estado en verdadero:
handleTitleInputSubmit() { this.setState(focusDescriptionInput: true); }
-
Al enviar / presionar enter / next en
TitleInput
, llamaremos ahandleTitleInputSubmit
. Esto estableceráfocusDescriptionInput
en verdadero.<TextInput style = {styles.titleInput} returnKeyType = {"next"} autoFocus = {true} placeholder = "Title" onSubmitEditing={this.handleTitleInputSubmit} />
-
El accesorio de
focus
DescriptionInput
se establece en nuestra variable de estadofocusDescriptionInput
. Entonces, cuandofocusDescriptionInput
cambia (en el paso 3),DescriptionInput
se volverá a representar confocus={true}
.<TextInput style = {styles.descriptionInput} multiline = {true} maxLength = {200} placeholder = "Description" focus={this.state.focusDescriptionInput} />
Esta es una buena manera de evitar el uso de referencias, ya que las referencias pueden conducir a un código más frágil :)
EDITAR: h / t a @LaneRettig para señalar que necesitará ajustar React Native TextInput con algunos accesorios y métodos adicionales para que responda al
focus
:
// Props:
static propTypes = {
focus: PropTypes.bool,
}
static defaultProps = {
focus: false,
}
// Methods:
focus() {
this._component.focus();
}
componentWillReceiveProps(nextProps) {
const {focus} = nextProps;
focus && this.focus();
}
Si está utilizando
tcomb-form-native
como yo, también puede hacerlo.
Aquí está el truco: en lugar de configurar los accesorios de
TextInput
directamente, lo haces a través de
options
.
Puede referirse a los campos del formulario como:
this.refs.form.getComponent(''password'').refs.input.focus()
Entonces el producto final se ve así:
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édito a remcoanker por publicar la idea aquí: https://github.com/gcanti/tcomb-form-native/issues/96 )
Si está utilizando NativeBase como componentes de la interfaz de usuario, puede usar este ejemplo
<Item floatingLabel>
<Label>Title</Label>
<Input
returnKeyType = {"next"}
autoFocus = {true}
onSubmitEditing={(event) => {
this._inputDesc._root.focus();
}} />
</Item>
<Item floatingLabel>
<Label>Description</Label>
<Input
getRef={(c) => this._inputDesc = c}
multiline={true} style={{height: 100}} />
onSubmitEditing={(event) => { this._inputLink._root.focus(); }} />
</Item>
Usando react-native 0.45.1 también encontré problemas al tratar de establecer el foco en una contraseña TextInput después de presionar la tecla de retorno en un nombre de usuario TextInput.
Después de haber probado la mayoría de las soluciones mejor calificadas aquí en SO, encontré una solución en github que satisfizo mis necesidades: https://github.com/shoutem/ui/issues/44#issuecomment-290724642
Para resumirlo:
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)}
/>
);
}
}
Y luego lo uso así:
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>
)
}
}
Usar referencias de devolución de llamada en lugar de las referencias de cadena legacy :
<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}
/>
en su componente:
<TextInput placeholder="Nombre"
ref="1"
editable={true}
returnKeyType="next"
underlineColorAndroid={''#4DB6AC''}
blurOnSubmit={false}
value={this.state.First_Name}
onChangeText={First_Name => this.setState({ First_Name })}
onSubmitEditing={() => this.focusNextField(''2'')}
placeholderTextColor="#797a7a" style={{ marginBottom: 10, color: ''#808080'', fontSize: 15, width: ''100%'', }} />
<TextInput placeholder="Apellido"
ref="2"
editable={true}
returnKeyType="next"
underlineColorAndroid={''#4DB6AC''}
blurOnSubmit={false}
value={this.state.Last_Name}
onChangeText={Last_Name => this.setState({ Last_Name })}
onSubmitEditing={() => this.focusNextField(''3'')}
placeholderTextColor="#797a7a" style={{ marginBottom: 10, color: ''#808080'', fontSize: 15, width: ''100%'', }} />
Nota: utilicé
._root
porque es una referencia a TextInput en
NativeBase''Library ''Input
y en tus entradas de texto como esta
focusNextField(nextField) {
this.refs[nextField].focus();
}
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} />
)
}
}
y agregar método
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();
}