Esta biblioteca resolverá estes problemas:
Quando definido windowSoftInputMode como adjustNothing
, os eventos React Native Keyboard, keyboardDidHide
e keyboardDidShow
, irão parar de funcionar (consulte o problema nº 2852).
Quando o teclado aparecer, todo o conteúdo do aplicativo será movido para cima (iOS e Android).
Para aplicativos de bate-papo que precisam manter a entrada de texto inferior na mesma posição ao dispensar o teclado e mostrar algumas ações, a mudança não será tão suave.
$ yarn add react-native-keyboard-area
É recomendado usar React Native > 0.60, o autolinking instalará este módulo RNKeyboard
nativo da biblioteca para iOS e Android.
No iOS: React Native fornece um componente chamado KeyboardAvoidingView
, envolva sua página com ele e ele moverá o conteúdo para cima quando o teclado aparecer.
No Android: por padrão, no AndroidManifest.xml, temos o windowSoftInputMode definido como adjustResize
, todo o conteúdo do aplicativo será movido para cima quando o teclado aparecer, portanto, não precisamos do componente KeyboardAvoidingView
.
Em ambos os sentidos, todo o conteúdo da página se moverá para cima ou para baixo e o teclado aparecerá ou desaparecerá.
Mas às vezes não precisamos de um aplicativo inteiro para subir, o exemplo mais comum é um aplicativo de bate-papo, podemos querer mudar para uma visualização personalizada quando o teclado desaparecer.
Esta biblioteca resolve o problema criando um componente wrapper KeyboardArea
, este componente ajustará sua altura para que o teclado apareça ou desapareça.
Além disso, também é possível controlar o estado com adereços isOpen
ou com os métodos open()
e close()
expostos.
Outro benefício é que o ReactNaive não irá redesenhar todo o aplicativo quando o teclado aparecer, pois a visualização principal não mudará de tamanho.
Antes : Usando ReactNative KeyboardAvoidingView e AdjustResize, o resultado não é muito bom, a página "salta" quando o teclado desaparece após a troca | Depois : Usando esta biblioteca, a visualização inteira não se moverá e a área do teclado sob a entrada manterá a mesma altura durante a troca |
Esta biblioteca possui algum código nativo iOS e Android para notificar, através de um evento chamado KeyboardSizeChanges
, o componente KeyboardArea
quando a altura do teclado muda.
No iOS usamos apenas UIResponder
keyboardWillShowNotification e keyboardWillHideNotification para então emitir o evento com a altura atual.
No Android precisamos definir o windowSoftInputMode como adjustNothing
, para evitar que o teclado suba toda a visualização, então criamos um PopupWindow
invisível para ouvir as mudanças de layout e medir a altura do teclado.
A maior parte da lógica está dentro do componente KeyboardArea
, só precisamos agrupar o conteúdo que queremos mostrar quando o teclado desaparecer e então definir os adereços isOpen quando precisarmos mostrar, no exemplo a seguir, o componente ChatActionsInput .
** esta é uma versão simplificada das imagens acima **
import { KeyboardArea , KeyboardAreaRef } from 'react-native-keyboard-area' ;
/// ...
keyboardSpacerRef = createRef < KeyboardSpacerRef > ( ) ;
handleUserClick = ( ) => {
this . keyboardSpacerRef . current ?. close ( ) ;
}
handleChangeMode = ( ) => {
this . setState ( prev => ( {
inputMode :
prev . inputMode === ChatInputModes . Actions
? ChatInputModes . Text
: ChatInputModes . Actions ,
} ) ) ;
}
keyboardAreaHeightChanged = ( isOpen : boolean , currentHeight : number ) => {
// Your logic
} ;
render ( ) {
return (
< PageContent >
< ChatMessageList />
< ChatTextInput onChangeMode = { this . handleChangeMode } />
< KeyboardSpacer
ref = { this . keyboardSpacerRef }
isOpen = { inputMode === ChatInputModes . Actions }
onChange = { this . keyboardAreaHeightChanged }
>
< ChatActionsInput />
</ KeyboardSpacer >
</ PageContent >
) ;
}
Como no Android podemos querer usar AdjustResize para as outras páginas, podemos usar esta biblioteca setWindowSoftInputMode
para alterar dinamicamente o modo SoftInput apenas para as páginas que precisamos, por exemplo:
import { RNKeyboard , SoftInputMode } from 'react-native-keyboard-area' ;
// Example with react-navigation page focus/blur events
componentDidMount ( ) {
navigation . addListener ( 'blur' , this . componentDidExit ) ;
navigation . addListener ( 'focus' , this . componentDidEnter ) ;
}
componentDidEnter = ( ) => {
if ( Platform . OS === 'android' ) {
RNKeyboard . setWindowSoftInputMode ( SoftInputMode . SOFT_INPUT_ADJUST_NOTHING , ) ;
}
} ;
componentDidExit = ( ) => {
if ( Platform . OS === 'android' ) {
RNKeyboard . setWindowSoftInputMode ( SoftInputMode . SOFT_INPUT_ADJUST_RESIZE ) ;
}
} ;
componentWillUnmount ( ) {
navigation . removeListener ( 'blur' , this . componentDidExit ) ;
navigation . removeListener ( 'focus' , this . componentDidEnter ) ;
}
Para Android, todos os créditos vão para Cristian Holdunu e Siebe Brouwer pela implementação da ideia PopupWindow
e para calcular a altura do teclado, acabei de portá-lo no sistema de módulos React Native.