Ocultar teclado no react-native

448

Se eu tocar em uma entrada de texto, desejo poder tocar em outro lugar para descartar o teclado novamente (mas não a tecla de retorno). Não encontrei a menor informação sobre isso em todos os tutoriais e postagens do blog que li.

Este exemplo básico ainda não está funcionando para mim com o 0.4.2 react-native no Simulator. Ainda não foi possível experimentá-lo no meu iPhone.

<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>
TurboFish
fonte
A resposta correta deve ser a de Eric Kim abaixo. A resposta ScrollView (definida como rolável como falsa) não é ideal, se você tiver várias entradas de texto, não permitirá que você salte da entrada de texto para a entrada de texto sem que o teclado seja descartado.
precisa saber é o seguinte
2
Para aqueles que querem uma solução para toda a aplicação ver @ resposta de Scottmas abaixo (link:. Stackoverflow.com/a/49825223/1138273 )
Hamed

Respostas:

563

O problema com o teclado não dispensar fica mais grave se você tiver keyboardType='numeric' , pois não há como descartá-lo.

Substituir o View pelo ScrollView não é uma solução correta, como se você tivesse vários textInputs ou buttons, tocar neles enquanto o teclado estiver levantado só descartará o teclado.

A maneira correta é encapsular o View com TouchableWithoutFeedbacke chamarKeyboard.dismiss()

EDIT: Agora você pode usar ScrollViewcom keyboardShouldPersistTaps='handled'para descartar o teclado apenas quando a torneira não é manuseada pelas crianças (por exemplo, tocando em outros textos).

Se você tem

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

Mude para

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

ou

import {Keyboard} from 'react-native'

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

EDIT: Você também pode criar um componente de ordem superior para descartar o 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)

Basta usá-lo assim

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

NOTA: accessible={false}é necessário para que o formulário de entrada continue acessível pelo VoiceOver. Pessoas com deficiência visual agradecerão!

Eric Kim
fonte
28
Isso é ótimo, o único comentário que tenho é que você poderia ter usado a API oficial do teclado no RN e chamado Keyboard.dismiss () em vez de chamar algum utilitário interno do RN, o allowKeyboard (). Mas ambos funcionam bem atualmente.
Pavle Lekic
@PavleLekic Desculpe pela demora, eu atualizei a resposta juntamente com o método HOC
Eric Kim
3
Isso funciona muito bem. Eu tive que mudar a sintaxe um pouco para a definição da função de seta, para remover um erro token inesperado no RN: const DismissKeyboardHOC = (Comp) => {
jwinn
2
Eu não posso obter onPresspara TouchableWithoutFeedbacka fogo, não importa o que eu tento
Brad Ryan
1
Por que criar um HoC e apenas adicioná-lo na raiz da sua árvore de aplicativos /
Dimitri Kopriwa
248

Isso acabou de ser atualizado e documentado ! Não há mais truques ocultos.

import { Keyboard } from 'react-native'

// Hide that keyboard!
Keyboard.dismiss()

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

Gant Laborde
fonte
4
Obrigado por adicionar isso. Espero que sua resposta borbulhe até o topo. Eu quase perdi e usei uma solução desatualizada.
sheepdog
2
Pinging @MrMuetze para mudar isso como a resposta correta
jehna1
8
Esta não deve ser a selecionada como a melhor resposta. A pergunta pergunta como descartar o teclado ao tocar fora dele. Essa resposta simplesmente fornece uma API para isso, enquanto a melhor resposta real fornece uma implementação viável.
jskidd3
você pode usar a próxima biblioteca: KeyboardAwareScrollView
Alejandro Gonzalez
97

use isso para dispensa personalizada

var dismissKeyboard = require('dismissKeyboard');

var TestView = React.createClass({
    render: function(){
        return (
            <TouchableWithoutFeedback 
                onPress={dismissKeyboard}>
                <View />
            </TouchableWithoutFeedback>
        )
    }
})
syarul
fonte
Não está documentado, mas as amostras no repositório github nativo do react usam-no algumas vezes.
syarul
7
Interessante, para aqueles curiosos de onde isso vem, é uma biblioteca de utilitários no React Native. Aqui está a fonte: github.com/facebook/react-native/blob/master/Libraries/…
Joshua Pinter
1
Por alguma razão não funcionou, quando eu tentei comreact-native-search-bar
Peter G.
Esse é o equivalente exato de Keyboard.dismiss, que é preferível, pois está documentado. github.com/facebook/react-native/blob/…
Ricardo Stuven
88

Use o React Native Keyboard.dismiss()

Resposta atualizada

O React Native expôs o dismiss()método estático no Keyboard, portanto, o método atualizado é:

import { Keyboard } from 'react-native'; 

Keyboard.dismiss()

Resposta original

Use o React Native dismissKeyboard biblioteca .

Eu tive um problema muito semelhante e senti que era o único que não entendia.

ScrollViews

Se você tem um ScrollView, ou qualquer coisa que herda dele como um ListView, você pode adicionar um suporte que descartará automaticamente o teclado com base em eventos de pressionar ou arrastar.

O suporte é keyboardDismissModee pode ter um valor de none, interactiveou on-drag. Você pode ler mais sobre isso aqui .

Visualizações regulares

Se você tiver algo diferente de a ScrollViewe desejar pressionar o teclado, use um simples TouchableWithoutFeedbacke onPressuse a biblioteca de utilitários do React Native dismissKeyboardpara dispensar o teclado para você.

No seu exemplo, você pode fazer algo assim:

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: TouchableWithoutFeedbacksó pode ter um único filho, portanto, você precisa agrupar tudo abaixo dele em um único, Viewcomo mostrado acima.

Joshua Pinter
fonte
4
Reagir nativo exposto a estática dismiss()método no teclado, então o método atualizado é: import { Keyboard } from 'react-native'; Keyboard.dismiss().
Joshua Pinter
1
Eu tenho um teclado que está pendurado desde que fiz uma recarga enquanto focado em um campo de entrada. neste caso Keyboard.dismiss(), nada faz, pois sua implementação depende de se concentrar em uma entrada, o que eu não sou mais.
pstanton
@pstanton O que você fez para dispensar o teclado?
Joshua Pinter
Não havia como encontrar, então forço o fechamento!
pstanton
41

A resposta simples é usar um ScrollView em vez de View e definir a propriedade rolável como false (pode ser necessário ajustar alguns estilos).

Dessa forma, o teclado é dispensado no momento em que toco em outro lugar. Isso pode ser um problema no react-native, mas os eventos de toque parecem ser tratados apenas com o ScrollViews, o que leva ao comportamento descrito.

Edit: Graças a jllodra. Observe que, se você tocar diretamente em outra entrada de texto e depois sair, o teclado ainda não será oculto.

TurboFish
fonte
1
Funciona com scrollview, mas ainda existem alguns casos em que posso clicar no botão para alterar a visualização usando o navegador e o teclado ainda na parte inferior e ter que clicar manualmente na tecla de retorno para fechá-la :(
Piyush Chauhan,
1
O teclado oculta quando você toca fora do TextInput, mas se (em vez de tocar fora) você toca em outro TextInput e, finalmente, toca fora, o teclado não se oculta. Testado em 0.6.0.
Jllodra
Estou vendo um comportamento diferente agora. Tocar fora do TextInput oculta o teclado, mesmo que eu toque diretamente em outro TextInput - o que é um problema, porque você precisa tocar duas vezes em outro TextInput para poder digitar nele! Suspiro. (com RN 0,19)
Lane Rettig 04/02
1
Você pode definir rolagem para verdadeiros e usar keyboardShouldPersistTaps = { 'manipulados'} e keyboardDismissMode = { 'on-drag'} para conseguir o mesmo efeito
Eric Wiener
apenas scrollview funcionou para mim Não sei por que, a resposta aceita quando digito um número de teclado dispensa
Yvon Huynh
33

Você pode importar keyboard do react-native como abaixo:

import { Keyboard } from 'react-native';

e no seu código pode ser algo como isto:

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

rejeição estática ()

Ignora o teclado ativo e remove o foco.

Alireza
fonte
Eu não precisava static dismiss(). Eu só acrescentou Keyboard.dismiss()ao meu método onSubmit (ondeonSubmitEditing={() => {this.onSubmit()}})
SherylHohman
30

Sou novato no React e tive exatamente o mesmo problema ao criar um aplicativo de demonstração. Se você usar o onStartShouldSetRespondersuporte (descrito aqui ), poderá tocar em um velho simples React.View. Curioso para ouvir os pensamentos dos Reagentes mais experientes sobre essa estratégia / se houver uma melhor, mas é isso que funcionou para mim:

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

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

2 coisas a serem observadas aqui. Primeiro, como discutido aqui , ainda não há uma maneira de terminar a edição de todas as subvisões, portanto, precisamos nos referir TextInputdiretamente ao para desfocá-lo. Segundo, ele onStartShouldSetResponderé interceptado por outros controles palpáveis ​​sobre ele. Portanto, clicar em um TouchableHighlightetc (incluindo outro TextInput) na visualização do contêiner não acionará o evento. No entanto, clicar em uma Imageexibição dentro do contêiner ainda descartará o teclado.

hunteros
fonte
Definitivamente funciona. Mas, como você disse, também estou curioso se esse é o caminho certo. Espero que eles resolvam isso em breve ( github.com/facebook/react-native/issues/113 )
mutp
Ótimo, isso funcionou para mim. Minha visualização de rolagem não estava funcionando com os métodos tocáveis! Obrigado!
21818 James Trickey
24

Use em ScrollViewvez de Viewe defina o keyboardShouldPersistTapsatributo como false.

<ScrollView style={styles.container} keyboardShouldPersistTaps={false}>
    <TextInput
        placeholder="Post Title"
        onChange={(event) => this.updateTitle(event.nativeEvent.text)}
        style={styles.default}/>
 </ScrollView>
Tyler McGinnis
fonte
De acordo com a documentação, o keyboardShouldPersistTapsatributo padrão é false ao usar a ScrollView. Acabei de atualizar meu react-native para a versão mais recente e o problema de mudar para um segundo TextInputainda persiste. O teclado não é descartável. Você encontrou uma solução para esse problema específico?
TurboFish
1
Os documentos estão incorretos, mas agora foram atualizados, consulte este PR: github.com/facebook/react-native/issues/2150
Ryan McDermott
O que keyboardShouldPersistTapsfaz? Por que é relevante aqui? Obrigado
Lane Rettig
1
Aviso: 'keyboardShouldPersistTaps = {false}' está obsoleto. Use 'keyboardShouldPersistTaps = "never"' em vez disso
Milan Rakos 04/04
13

Se alguém precisar de um exemplo prático de como descartar uma entrada de texto com várias linhas, aqui está! Espero que isso ajude algumas pessoas por aí, os documentos não descrevem uma maneira de descartar uma entrada de várias linhas, pelo menos não houve referência específica sobre como fazê-lo. Ainda é um noob para realmente postar aqui na pilha, se alguém achar que isso deve ser uma referência à postagem real em que este snippet foi escrito para me avisar.

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>
    )
  }
}
austin reynolds
fonte
11

Uso atualizado de ScrollViewparaReact Native 0.39

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

Embora ainda haja um problema com duas TextInputcaixas. por exemplo. Um formulário de nome de usuário e senha agora descartaria o teclado ao alternar entre entradas. Gostaria de receber algumas sugestões para manter o teclado ativo ao alternar entre TextInputsenquanto usa um ScrollView.

Anshul Koka
fonte
3
Parece que as 0.40atualizações keyboardShouldPersistTapsde um booleanpara um enumcom um possível valor de 'manipulado', que é suposto corrigir isso.
Anshul Koka
11

Existem algumas maneiras, se você controla um evento como onPressvocê pode usar:

import { Keyboard } from 'react-native'

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

se você deseja fechar o teclado quando usar a rolagem:

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

Mais opção é quando o usuário clica fora do teclado:

<KeyboardAvoidingView behavior='padding' style={{ flex: 1}}>
    //inputs and other content
</KeyboardAvoidingView>
Idan
fonte
1
Gente, a pergunta ainda é real, mas ela tem 4 anos (final de 2019 agora). RN agora é tão simples e fácil de usar. Temos que revisar todas as habilidades com a ajuda de podemos obter uma solução para esta pergunta. Vamos votar este comentário!
Link
@Link Oi, obrigado! Estou absolutamente de acordo
Idan
10
const dismissKeyboard = require('dismissKeyboard');
dismissKeyboard(); //dismisses it

Abordagem nº 2;

Obrigado ao usuário @ ricardo-stuven por apontar isso, há outra maneira melhor de descartar o teclado que você pode ver no exemplo nos documentos nativos do react.

Importação simples Keyboarde chame seu métododismiss()

Adeel Imran
fonte
1
Esse é o equivalente exato de Keyboard.dismiss, que é preferível, pois está documentado. github.com/facebook/react-native/blob/…
Ricardo Stuven
No momento em que dei essa resposta, isso não estava documentado. Obrigado por mencionar. Vou atualizar minha resposta.
Adeel Imran
10

A quebra de seus componentes em um TouchableWithoutFeedbackpode causar um comportamento estranho de rolagem e outros problemas. Prefiro agrupar meu aplicativo superior em um Viewcom a onStartShouldSetResponderpropriedade preenchida. Isso me permitirá lidar com todos os toques sem tratamento e depois dispensar o teclado. É importante ressaltar que, como a função do manipulador retorna false, o evento touch é propagado como normal.

 handleUnhandledTouches(){
   Keyboard.dismiss
   return false;
 }

 render(){
    <View style={{ flex: 1 }} onStartShouldSetResponder={this.handleUnhandledTouches}>
       <MyApp>
    </View>
  }
Scottmas
fonte
Obrigado pela sua resposta @ Scottmas. Acabei usando-o em vez de TouchableWithoutFeedback, por causa do seu comentário "comportamento de rolagem estranho e outros problemas". Mas se eu não confiava cegamente em suas palavras, você pode elaborar seu comentário? :)
kuhr 17/03
8

Acabei de testar isso usando a versão mais recente do React Native (0.4.2), e o teclado é descartado quando você toca em outro lugar.

E FYI: você pode definir uma função de retorno de chamada a ser executada quando você ignora o teclado, atribuindo-o ao suporte "onEndEditing".

Jonathan Huang
fonte
Eu estava depurando o retorno de chamada "onEndEditing", mas ele nunca foi acionado antes; Eu vou olhar para isso com a versão mais recente reagir nativas, obrigado pela sua sugestão
TurboFish
7

Se não me engano, a versão mais recente do React Native resolveu esse problema de poder descartar o teclado tocando.

christopherdro
fonte
4
Você seria capaz de apontar qual parte do código / documento deles faz isso? Estou correndo para o mesmo problema, e eu realmente aprecio isso me apontando para a direção :)
Okazaki Miyama Yuta
Confirmado que este ainda é um problema a partir do RN 0.19 (o mais recente).
Lane Rettig
Ainda um problema com RN 0,28
hippofluff
7

Que tal colocar um componente palpável ao redor / ao lado do 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>
        )
    }
}
boredgames
fonte
6

Enrole todo o seu componente com:

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

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

Trabalhou para mim

Arthur Mastropietro
fonte
4

O módulo do teclado é usado para controlar eventos do teclado.

  • import { Keyboard } from 'react-native'
  • Adicione o código abaixo no método de renderização.

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

Você pode usar -

Keyboard.dismiss()

descarte estático () Descarta o teclado ativo e remove o foco conforme reage aos documentos nativos.

sharma abhinandan
fonte
3

Primeira importação do teclado

import { Keyboard } from 'react-native'

Então, dentro do seu, TextInputvocê adiciona Keyboard.dismissao onSubmitEditingsuporte. Você deve ter algo parecido com isto:

render(){
  return(
    <View>
      <TextInput 
        onSubmitEditing={Keyboard.dismiss}
       />
    </View>
  )  
}
Nagendra kr.
fonte
1
Mais contexto seria bom.
Colidyre 12/10
2

Usando keyboardShouldPersistTapsno ScrollViewvocê pode passar "manipulado", que lida com os problemas que as pessoas estão dizendo que vêm com o uso do ScrollView. Isto é o que a documentação diz sobre o uso de 'manipulado': the keyboard will not dismiss automatically when the tap was handled by a children, (or captured by an ancestor). Aqui é onde é referenciado.

Samuel
fonte
Isso funcionou para mim! (no entanto, tive que adicioná-lo na minha biblioteca de terceiros react-native-keyboard-aware-scroll-view).
Nick Grealy
1

em ScrollViewuso

keyboardShouldPersistTaps="handled" 

Isso fará o seu trabalho.

gamingumar
fonte
1

Existem várias maneiras de lidar com isso, as respostas acima não incluem, returnTypepois não foram incluídas no nativo do reagir naquele momento.

1: Você pode resolvê-lo envolvendo seus componentes dentro do ScrollView; por padrão, o ScrollView fecha o teclado se pressionarmos em algum lugar. Mas, caso você queira usar o ScrollView, desative esse efeito. você pode usar prop pointerEvent para scrollView pointerEvents = 'none'.

2: Se você deseja fechar o teclado pressionando um botão, basta usar a Keyboardpartir dereact-native

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

3: Você também pode fechar o teclado ao clicar na tecla de retorno do teclado. NOTA: se o seu tipo de teclado for numérico, você não terá uma tecla de retorno. Portanto, você pode habilitá-lo fornecendo uma proposta, returnKeyType paradone . ou você pode usar onSubmitEditing={Keyboard.dismiss}, ele é chamado sempre que pressionamos a tecla Enter. E se você quiser descartar o teclado ao perder o foco, poderá usar o suporte onBlur,onBlur = {Keyboard.dismiss}

Sarmad Shah
fonte
0

Keyboard.dismiss()vai fazer isso. Mas, às vezes, pode perder o foco e o Teclado não conseguirá encontrar o árbitro. A maneira mais consistente de fazer isso é colocar um ref=_refno textInput e fazê- _ref.blur()lo quando precisar dispensar e _ref.focus()quando precisar devolver o teclado.

Bruce Xinda Lin
fonte
0

experimente keyboard.dismiss(). Funcionou para mim

Amoli
fonte
0

Aqui está minha solução para descartar e rolar o teclado para TextInput tocado (estou usando o ScrollView com o suporte keyboardDismissMode):

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>
   );
}

Artem Shevtsov
fonte
0

use este pacote react-native-keyboard-aware-scroll-view

use esse componente como seu componente raiz

Como este pacote react-native-keyboard-aware-scroll-viewtambém possui um scrollView, você precisa adicioná-lo a ele:

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

Cyrus Zei
fonte