Ocultar teclado en react-native


448

Si toco una entrada de texto, quiero poder tocar en otro lugar para cerrar nuevamente el teclado (aunque no la tecla de retorno). No he encontrado la más mínima información sobre esto en todos los tutoriales y publicaciones de blog que leí.

Este ejemplo básico todavía no me funciona con react-native 0.4.2 en el simulador. No pude probarlo en mi iPhone todavía.

<View style={styles.container}>
    <Text style={styles.welcome}>
      Welcome to React Native!
    </Text>
    <Text style={styles.instructions}>
      To get started, edit index.ios.js
    </Text>
    <Text style={styles.instructions}>
      Press Cmd+R to reload,{'\n'}
      Cmd+D or shake for dev menu
    </Text>
    <TextInput
      style={{height: 40, borderColor: 'gray', borderWidth: 1}}
      onEndEditing={this.clearFocus}
    />
  </View>


La respuesta correcta debería ser la de Eric Kim a continuación. La respuesta ScrollView (configurada como desplazable a falso) no es ideal, si tiene múltiples entradas de texto, no le permite saltar de entrada de texto a entrada de texto sin que se descarte el teclado.
hippofluff

2
Para aquellos que desean una solución para toda la aplicación, consulte la respuesta de @ Scottmas a continuación. (Enlace: stackoverflow.com/a/49825223/1138273 )
Hamed

Respuestas:


563

El problema con el teclado no se descarta se vuelve más grave si lo tiene keyboardType='numeric', ya que no hay forma de descartarlo.

Reemplazar la vista con ScrollView no es una solución correcta, ya que si tiene múltiples textInputso buttons, tocarlas mientras el teclado está arriba solo descartará el teclado.

La forma correcta es encapsular View con TouchableWithoutFeedbacky llamandoKeyboard.dismiss()

EDITAR: ahora puede usar ScrollViewcon keyboardShouldPersistTaps='handled'solo descartar el teclado cuando los niños no manejan el toque (es decir, tocando otras entradas o botones de texto)

Si usted tiene

<View style={{flex: 1}}>
    <TextInput keyboardType='numeric'/>
</View>

Cámbialo a

<ScrollView contentContainerStyle={{flexGrow: 1}}
  keyboardShouldPersistTaps='handled'
>
  <TextInput keyboardType='numeric'/>
</ScrollView>

o

import {Keyboard} from 'react-native'

<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
    <View style={{flex: 1}}>
        <TextInput keyboardType='numeric'/>
    </View>
</TouchableWithoutFeedback>

EDITAR: También puede crear un Componente de orden superior para descartar el teclado.

import React from 'react';
import { TouchableWithoutFeedback, Keyboard, View } from 'react-native';

const DismissKeyboardHOC = (Comp) => {
  return ({ children, ...props }) => (
    <TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
      <Comp {...props}>
        {children}
      </Comp>
    </TouchableWithoutFeedback>
  );
};
const DismissKeyboardView = DismissKeyboardHOC(View)

Simplemente úsalo así

...
render() {
    <DismissKeyboardView>
        <TextInput keyboardType='numeric'/>
    </DismissKeyboardView>
}

NOTA: accessible={false}se requiere para que el formulario de entrada siga siendo accesible a través de VoiceOver. ¡Las personas con discapacidad visual se lo agradecerán!


28
Esto es genial, el único comentario que tengo es que podrías haber usado la API oficial de Teclado en RN y haber llamado Keyboard.dismiss () en lugar de llamar a alguna utilidad interna de RN para descartar Keyboard (). Pero ambos funcionan bien actualmente.
Pavle Lekic

@PavleLekic Perdón por el retraso, actualicé la respuesta junto con el método HOC
Eric Kim

3
Esto funciona muy bien. Tuve que cambiar un poco la sintaxis para la definición de la función de flecha, para eliminar un error de token inesperado en RN: const DismissKeyboardHOC = (Comp) => {
jwinn

2
No puedo conseguir onPresspara TouchableWithoutFeedbackque el fuego no importa lo que intento
Brad Ryan

1
¿Por qué crear un HoC y simplemente agregarlo en la raíz de su árbol de aplicaciones? /
Dimitri Kopriwa

248

¡Esto acaba de actualizarse y documentarse ! No más trucos ocultos.

import { Keyboard } from 'react-native'

// Hide that keyboard!
Keyboard.dismiss()

https://github.com/facebook/react-native/pull/9925


44
Gracias por agregar esto. Espero que tu respuesta llegue a la cima. Casi me lo pierdo y utilicé una solución desactualizada.
perro pastor el

2
Pinging @MrMuetze para cambiar esto como la respuesta correcta
jehna1

8
Esta no debería ser la seleccionada como la mejor respuesta. La pregunta pregunta cómo descartar el teclado cuando se toca fuera de él. Esta respuesta simplemente proporciona una API para hacerlo, mientras que la mejor respuesta real proporciona una implementación viable.
jskidd3

puedes usar la siguiente biblioteca: KeyboardAwareScrollView
Alejandro Gonzalez

97

use esto para el despido personalizado

var dismissKeyboard = require('dismissKeyboard');

var TestView = React.createClass({
    render: function(){
        return (
            <TouchableWithoutFeedback 
                onPress={dismissKeyboard}>
                <View />
            </TouchableWithoutFeedback>
        )
    }
})

No está documentado, pero las muestras en el repositorio de Github nativo de Reacción lo usan pocas veces.
syarul

77
Interesante, para aquellos curiosos de dónde viene esto, es una biblioteca de utilidades en React Native. Aquí está la fuente: github.com/facebook/react-native/blob/master/Libraries/…
Joshua Pinter el

1
Por alguna razón no funcionó, cuando trataba conreact-native-search-bar
Peter G.

Este es el equivalente exacto de Keyboard.dismiss, que es preferible ya que está documentado. github.com/facebook/react-native/blob/…
Ricardo Stuven

88

Utilice React Native's Keyboard.dismiss()

Respuesta actualizada

React Native expuso el dismiss()método estático en el Keyboard, por lo que el método actualizado es:

import { Keyboard } from 'react-native'; 

Keyboard.dismiss()

Respuesta original

Utilice React Native's dismissKeyboardLibrary.

Tuve un problema muy similar y sentí que era el único que no lo entendió.

ScrollViews

Si tiene un ScrollView, o cualquier cosa que herede de él como un ListView, puede agregar un accesorio que descartará automáticamente el teclado en función de eventos de prensa o arrastre.

El accesorio es keyboardDismissModey puede tener un valor de none, interactiveo on-drag. Puedes leer más sobre eso aquí .

Vistas regulares

Si tiene algo diferente a ScrollVieway desea presionar para descartar el teclado, puede usar uno simple TouchableWithoutFeedbacky onPressusar la biblioteca de utilidades React Native dismissKeyboardpara descartar el teclado por usted.

En su ejemplo, podría hacer algo como esto:

var DismissKeyboard = require('dismissKeyboard'); // Require React Native's utility library.

// Wrap your view with a TouchableWithoutFeedback component like so.

<View style={styles.container}>

  <TouchableWithoutFeedback onPress={ () => { DismissKeyboard() } }>

    <View>

      <Text style={styles.welcome}>
        Welcome to React Native!
      </Text>

      <Text style={styles.instructions}>
        To get started, edit index.ios.js
      </Text>

      <Text style={styles.instructions}>
        Press Cmd+R to reload,{'\n'}
        Cmd+D or shake for dev menu
      </Text>

      <TextInput style={{height: 40, borderColor: 'gray', borderWidth: 1}} />

    </View>

  </TouchableWithoutFeedback>

</View>

Nota: TouchableWithoutFeedbacksolo puede tener un solo hijo, por lo que debe envolver todo debajo de él en uno solo Viewcomo se muestra arriba.


44
Reaccionar nativo expuso la estática dismiss()método en el teclado, por lo que el método de actualización es: import { Keyboard } from 'react-native'; Keyboard.dismiss().
Joshua Pinter

1
Tengo un teclado que está dando vueltas desde que hice una recarga mientras estaba enfocado en un campo de entrada. en este caso Keyboard.dismiss()no hace nada ya que su implementación depende de que se centre en una entrada, que ya no soy.
pstanton

@pstanton ¿Qué tuviste que hacer para descartar el teclado?
Joshua Pinter

No había forma de encontrarlo, ¡así que forcé el cierre!
pstanton

41

La respuesta simple es usar un ScrollView en lugar de View y establecer la propiedad desplazable en false (aunque podría necesitar un poco de estilo).

De esta manera, el teclado se descarta en el momento en que toco en otro lugar. Esto podría ser un problema con react-native, pero los eventos de tap solo parecen manejarse con ScrollViews, lo que conduce al comportamiento descrito.

Editar: Gracias a jllodra. Tenga en cuenta que si toca directamente en otra entrada de texto y luego afuera, el teclado aún no se ocultará.


1
Funciona con scrollview pero todavía hay algunos casos en los que estoy experimentando donde puedo hacer clic en el botón para cambiar la vista usando el navegador y el teclado todavía se pega en la parte inferior y tengo que hacer clic manualmente en la tecla de retorno para cerrarlo :(
Piyush Chauhan

1
El teclado se oculta cuando toca fuera de TextInput, pero si (en lugar de tocar afuera) toca otro TextInput y finalmente toca afuera, el teclado no se oculta. Probado en 0.6.0.
jllodra

Estoy viendo un comportamiento diferente ahora. Tocar fuera de TextInput oculta el teclado, incluso si toco directamente en otro TextInput, lo cual es un problema porque tienes que tocar dos veces en otro TextInput para poder escribir en él. Suspiro. (con RN 0.19)
Lane Rettig

1
Puede establecer desplazable en verdadero y usar keyboardShouldPersistTaps = {'handle'} y keyboardDismissMode = {'on-drag'} para lograr el mismo efecto
Eric Wiener

solo scrollview funcionó para mí No sé por qué, la respuesta aceptada cuando ingreso un número de teclado se descarta
Yvon Huynh

33

Puede importar keyboard desde react-native como a continuación:

import { Keyboard } from 'react-native';

y en su código podría haber algo como esto:

render() {
    return (
      <TextInput
        onSubmit={Keyboard.dismiss}
      />
    );
  }

despido estático ()

Descarta el teclado activo y elimina el foco.


No lo necesitaba static dismiss(). Acabo de agregar Keyboard.dismiss()a mi método onSubmit (dondeonSubmitEditing={() => {this.onSubmit()}})
SherylHohman

30

Soy nuevo en React y me encontré exactamente con el mismo problema al hacer una aplicación de demostración. Si usa el onStartShouldSetResponderaccesorio (descrito aquí ), puede obtener toques en un viejo plano React.View. Curioso por escuchar los pensamientos de los Reactores más experimentados sobre esta estrategia / si hay una mejor, pero esto es lo que funcionó para mí:

containerTouched(event) {
  this.refs.textInput.blur();
  return false;
}

render() {
  <View onStartShouldSetResponder={this.containerTouched.bind(this)}>
    <TextInput ref='textInput' />
  </View>
}

2 cosas a tener en cuenta aquí. Primero, como se discutió aquí , todavía no hay una forma de finalizar la edición de todas las subvistas, por lo que debemos referirnos TextInputdirectamente a él para desenfocarlo. En segundo lugar, el onStartShouldSetResponderes interceptado por otros controles táctiles en la parte superior. Por lo tanto, hacer clic en un TouchableHighlightetc. (incluido otro TextInput) dentro de la vista del contenedor no activará el evento. Sin embargo, al hacer clic en un Imagedentro de la vista del contenedor, se cerrará el teclado.


Definitivamente funciona. Pero como dijiste, también tengo curiosidad si esta es la forma correcta. Espero que lo resuelvan pronto ( github.com/facebook/react-native/issues/113 )
mutp

Genial, esto funcionó para mí. ¡Mi vista de desplazamiento no funcionaba con los métodos táctiles! ¡Gracias!
James Trickey

24

Use en ScrollViewlugar de Viewy establezca el keyboardShouldPersistTapsatributo en falso.

<ScrollView style={styles.container} keyboardShouldPersistTaps={false}>
    <TextInput
        placeholder="Post Title"
        onChange={(event) => this.updateTitle(event.nativeEvent.text)}
        style={styles.default}/>
 </ScrollView>

De acuerdo con la documentación, el keyboardShouldPersistTapsatributo predeterminado es falso cuando se usa a ScrollView. Acabo de actualizar mi react-native a la última versión y el problema de cambiar a un segundo TextInputaún persiste. El teclado no es descartable. ¿Has encontrado una solución para este problema específico?
TurboFish

1
Los documentos eran incorrectos, pero ahora se han actualizado, vea este PR: github.com/facebook/react-native/issues/2150
Ryan McDermott

¿Qué keyboardShouldPersistTapshacer? ¿Por qué es relevante aquí? Gracias
Lane Rettig

1
Advertencia: 'keyboardShouldPersistTaps = {false}' está en desuso. Use 'keyboardShouldPersistTaps = "never"' en su lugar
Milan Rakos

13

Si alguien necesita un ejemplo práctico de cómo descartar una entrada de texto multilínea aquí ¡ya está! Espero que esto ayude a algunas personas, los documentos no describen una forma de descartar una entrada multilínea, al menos no hubo una referencia específica sobre cómo hacerlo. Todavía es un novato para publicar aquí en la pila, si alguien piensa que esto debería ser una referencia a la publicación real para la que se escribió este fragmento, hágamelo saber.

import React, { Component } from 'react'
import {
  Keyboard,
  TextInput,
  TouchableOpacity,
  View,
  KeyboardAvoidingView,
} from 'react-native'

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      behavior: 'position',
    }
    this._keyboardDismiss = this._keyboardDismiss.bind(this)
  }

  componentWillMount() {
    this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
  }

  componentWillUnmount() {
    this.keyboardDidHideListener.remove()
  }

  _keyboardDidHide() {
    Keyboard.dismiss()
  }

  render() {
    return (
      <KeyboardAvoidingView
        style={{ flex: 1 }}
        behavior={this.state.behavior}
      >
        <TouchableOpacity onPress={this._keyboardDidHide}>
          <View>
            <TextInput
              style={{
                color: '#000000',
                paddingLeft: 15,
                paddingTop: 10,
                fontSize: 18,
              }}
              multiline={true}
              textStyle={{ fontSize: '20', fontFamily: 'Montserrat-Medium' }}
              placeholder="Share your Success..."
              value={this.state.text}
              underlineColorAndroid="transparent"
              returnKeyType={'default'}
            />
          </View>
        </TouchableOpacity>
      </KeyboardAvoidingView>
    )
  }
}

11

Uso actualizado de ScrollViewforReact Native 0.39

<ScrollView scrollEnabled={false} contentContainerStyle={{flex: 1}} />

Aunque, todavía hay un problema con dos TextInputcajas. p.ej. Un formulario de nombre de usuario y contraseña ahora descartaría el teclado al cambiar entre entradas. Me encantaría obtener algunas sugerencias para mantener vivo el teclado al cambiar entre TextInputsmientras se usa a ScrollView.


3
Parece que las 0.40actualizaciones keyboardShouldPersistTapsde una booleana una enumcon un posible valor de 'manejado' que se supone que solucionan esto.
Anshul Koka

11

Hay algunas maneras, si puede controlar un evento como onPresspuede usar:

import { Keyboard } from 'react-native'

onClickFunction = () => {
     Keyboard.dismiss()
}

si desea cerrar el teclado cuando use el desplazamiento:

<ScrollView keyboardDismissMode={'on-drag'}>
     //content
</ScrollView>

Más opción es cuando el usuario hace clic fuera del teclado:

<KeyboardAvoidingView behavior='padding' style={{ flex: 1}}>
    //inputs and other content
</KeyboardAvoidingView>

1
Chicos, la pregunta sigue siendo real, pero tiene 4 años (a finales de 2019 ahora). RN ahora es muy simple y fácil de usar. Tenemos que revisar todas las habilidades con la ayuda de que podemos lograr una solución para esta pregunta. ¡Vota este comentario!
Enlace del

@ Link Hola, gracias! Estoy absolutamente de acuerdo
Idan

10
const dismissKeyboard = require('dismissKeyboard');
dismissKeyboard(); //dismisses it

Enfoque n. ° 2;

Gracias al usuario @ ricardo-stuven por señalar esto, hay otra manera mejor de descartar el teclado que puede ver en el ejemplo en los documentos nativos de reacción.

Importación simple Keyboardy llame a su métododismiss()


1
Este es el equivalente exacto de Keyboard.dismiss, que es preferible ya que está documentado. github.com/facebook/react-native/blob/…
Ricardo Stuven

En el momento en que di esta respuesta, esto no estaba documentado. Gracias por mencionarlo. Actualizaré mi respuesta.
Adeel Imran

10

Ajustar sus componentes en un TouchableWithoutFeedbackpuede causar un comportamiento de desplazamiento extraño y otros problemas. Prefiero envolver mi aplicación superior en una Viewcon la onStartShouldSetResponderpropiedad completada. Esto me permitirá manejar todos los toques no manejados y luego cerrar el teclado. Es importante destacar que, dado que la función del controlador devuelve falso, el evento táctil se propaga de manera normal.

 handleUnhandledTouches(){
   Keyboard.dismiss
   return false;
 }

 render(){
    <View style={{ flex: 1 }} onStartShouldSetResponder={this.handleUnhandledTouches}>
       <MyApp>
    </View>
  }

Gracias por tu respuesta @Scottmas. Terminé usándolo en lugar de TouchableWithoutFeedback, debido a su comentario de "comportamiento de desplazamiento extraño y otros problemas". Pero si no confiaba ciegamente en tus palabras, ¿puedes dar más detalles sobre tu comentario? :)
kuhr

8

Acabo de probar esto usando la última versión React Native (0.4.2), y el teclado se cierra cuando tocas en otro lado.

Y para su información: puede configurar una función de devolución de llamada para que se ejecute cuando descarta el teclado asignándolo al accesorio "onEndEditing".


Estaba depurando la devolución de llamada "onEndEditing", pero nunca se activó antes; Voy a investigar esto con la versión más nueva de react native, gracias por su sugerencia
TurboFish

7

Si no me equivoco, la última versión de React Native ha resuelto este problema de poder cerrar el teclado tocando.


44
¿Serías capaz de señalar qué parte de su código / documento hace eso? Me encuentro con el mismo problema, y ​​realmente aprecio que me haya señalado la dirección :)
Okazaki Miyama Yuta

Confirmó que esto sigue siendo un problema a partir de RN 0.19 (la última).
Lane Rettig

Sigue siendo un problema con RN 0.28
hippofluff

7

¿Qué hay de colocar un componente táctil alrededor / al lado del TextInput?

var INPUTREF = 'MyTextInput';

class TestKb extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <View style={{ flex: 1, flexDirection: 'column', backgroundColor: 'blue' }}>
                <View>
                    <TextInput ref={'MyTextInput'}
                        style={{
                            height: 40,
                            borderWidth: 1,
                            backgroundColor: 'grey'
                        }} ></TextInput>
                </View>
                <TouchableWithoutFeedback onPress={() => this.refs[INPUTREF].blur()}>
                    <View 
                        style={{ 
                            flex: 1, 
                            flexDirection: 'column', 
                            backgroundColor: 'green' 
                        }} 
                    />
                </TouchableWithoutFeedback>
            </View>
        )
    }
}

6

Envuelva todo su componente con:

import { TouchableWithoutFeedback, Keyboard } from 'react-native'

<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
...
</TouchableWithoutFeedback>

Trabajó para mi



4

El módulo de teclado se usa para controlar eventos de teclado.

  • import { Keyboard } from 'react-native'
  • Agregue el siguiente código en el método de representación.

    render() { return <TextInput onSubmitEditing={Keyboard.dismiss} />; }

Puedes usar -

Keyboard.dismiss()

despido estático () Descarta el teclado activo y elimina el foco según los documentos nativos de reacción.


3

Primer teclado de importación

import { Keyboard } from 'react-native'

Luego dentro de tu TextInputagregas Keyboard.dismissal onSubmitEditingaccesorio. Deberías tener algo parecido a esto:

render(){
  return(
    <View>
      <TextInput 
        onSubmitEditing={Keyboard.dismiss}
       />
    </View>
  )  
}

1
Más contexto estaría bien.
colidyre

2

Usando keyboardShouldPersistTapsen el ScrollViewpuede pasar en "manejado", que se ocupa de los problemas que la gente dice que viene con el uso de ScrollView. Esto es lo que dice la documentación sobre el uso de 'manejado': the keyboard will not dismiss automatically when the tap was handled by a children, (or captured by an ancestor). Aquí es donde se hace referencia.


¡Esto funcionó para mí! (Sin embargo, tuve que agregarlo dentro de mi biblioteca de terceros react-native-keyboard-aware-scroll-view).
Nick Grealy

1

en ScrollViewuso

keyboardShouldPersistTaps="handled" 

Esto hará tu trabajo.


1

Hay muchas formas de manejar esto, las respuestas anteriores no incluyen, returnTypeya que no se incluyó en react-native esa vez.

1: Puede resolverlo envolviendo sus componentes dentro de ScrollView, por defecto ScrollView cierra el teclado si presionamos en algún lugar. Pero en caso de que quiera usar ScrollView pero deshabilite este efecto. puedes usar pointerEvent prop para scrollView pointerEvents = 'none'.

2: Si desea cerrar el teclado al presionar un botón, puede usar Keyboarddesdereact-native

import { Keyboard } from 'react-native' and inside onPress of that button, you can useKeyboard.dismiss () '.

3: También puede cerrar el teclado cuando hace clic en la tecla de retorno en el teclado, NOTA: si su tipo de teclado es numérico, no tendrá una tecla de retorno. Por lo tanto, puede habilitarlo dándole un accesorio, returnKeyType a done. o puede usar onSubmitEditing={Keyboard.dismiss}, se llama cada vez que presionamos la tecla de retorno. Y si desea descartar el teclado al perder el foco, puede usar onBlur prop,onBlur = {Keyboard.dismiss}


0

Keyboard.dismiss()lo haré. Pero a veces puede perder el foco y Keyboard no podrá encontrar la referencia. La forma más coherente de hacerlo es poner una entrada ref=_refde texto, y hacerlo _ref.blur()cuando necesite descartar, y _ref.focus()cuando necesite recuperar el teclado.



0

Aquí está mi solución para descartar y desplazar el teclado a TextInput girado (estoy usando ScrollView con keyboardDismissMode prop):

import React from 'react';
import {
  Platform,
  KeyboardAvoidingView,
  ScrollView
} from 'react-native';

const DismissKeyboard = ({ children }) => {
  const isAndroid = Platform.OS === 'android';
  const behavior = isAndroid ? false : 'padding';

  return (
    <KeyboardAvoidingView
      enabled
      behavior={ behavior }
      style={{ flex: 1}}
    >
      <ScrollView
        keyboardShouldPersistTaps={'always'}
        keyboardDismissMode={'on-drag'}
      >
        { children }
      </ScrollView>
    </KeyboardAvoidingView>
  );
};

export default DismissKeyboard;

uso:

render(){
   return(
     <DismissKeyboard>
       <TextInput
        style={{height: 40, borderColor: 'gray', borderWidth: 1}}
        onChangeText={(text) => this.setState({text})}
        value={this.state.text}
      />
     </DismissKeyboard>
   );
}


0

usa este paquete react-native-keyboard-aware-scroll-view

usa ese componente como tu componente raíz

react-native-keyboard-aware-scroll-viewComo este paquete también tiene scrollView, debe agregarlo:

<KeyboardAwareScrollView keyboardShouldPersistTaps="handled"> <ScrollView keyboardShouldPersistTaps="handled"></ScrollView> </KeyboardAwareScrollView>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.