Эта библиотека решит следующие проблемы:
Если для windowSoftInputMode установлено adjustNothing
, события React Native Keyboard, keyboardDidHide
и keyboardDidShow
перестанут работать (см. проблему № 2852).
Когда появится клавиатура, все содержимое приложения переместится вверх (iOS и Android).
Для приложения чата, которому необходимо сохранять нижнюю часть ввода текста в том же положении при закрытии клавиатуры и отображении некоторых действий, переключение не будет таким плавным.
$ yarn add react-native-keyboard-area
Рекомендуется использовать React Native > 0.60, при автоматическом связывании будет установлен собственный модуль RNKeyboard
этой библиотеки для iOS и Android.
В iOS: React Native предоставляет компонент под названием KeyboardAvoidingView
, оберните им свою страницу, и он будет перемещать содержимое вверх при появлении клавиатуры.
В Android: по умолчанию в AndroidManifest.xml для параметра windowSoftInputMode установлено adjustResize
, все содержимое приложения будет перемещаться вверх при появлении клавиатуры, поэтому нам не нужен компонент KeyboardAvoidingView
.
В обоих случаях все содержимое страницы будет перемещаться вверх или вниз, после чего клавиатура появится или исчезнет.
Но иногда нам не нужно перемещаться вверх по всему приложению, наиболее распространенным примером является приложение чата, мы можем захотеть переключиться на пользовательский вид , когда клавиатура исчезнет.
Эта библиотека решает проблему, создавая компонент-оболочку KeyboardArea
, этот компонент будет регулировать свою высоту, после чего клавиатура появится или исчезнет.
Кроме того, также возможно управлять состоянием с помощью свойств isOpen
или с помощью открытых методов open()
и close()
.
Еще одним преимуществом является то, что ReactNaive не будет перерисовывать все приложение при появлении клавиатуры, поскольку размер основного вида не изменится.
До : Использование ReactNative KeyboardAvoidingView и корректировкиResize, результат не очень хороший, страница "подпрыгивает", когда клавиатура исчезает после переключения | После : при использовании этой библиотеки весь вид не будет перемещаться, а область клавиатуры под вводом будет сохранять ту же высоту во время переключения. |
В этой библиотеке есть собственный код iOS и Android для уведомления через событие KeyboardSizeChanges
компонента KeyboardArea
об изменении высоты клавиатуры.
В iOS мы просто используем UIResponder
KeyboardWillShowNotification и KeyboardWillHideNotification, чтобы затем генерировать событие с текущей высотой.
В Android нам нужно установить для windowSoftInputMode значение adjustNothing
, чтобы клавиатура не перемещалась вверх по всему представлению, затем мы создаем невидимый PopupWindow
чтобы прослушивать изменения макета и измерять высоту клавиатуры.
Большая часть логики находится внутри компонента KeyboardArea
, нам просто нужно обернуть контент, который мы хотим показать, когда клавиатура исчезнет, а затем установить реквизиты isOpen , когда нам нужно показать, в следующем примере, компонент ChatActionsInput .
** это упрощенная версия приведенных выше скриншотов **
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 >
) ;
}
Поскольку в Android нам может потребоваться использовать настройку AdjustResize для других страниц, мы можем использовать эту библиотеку setWindowSoftInputMode
для динамического изменения режима SoftInput только для тех страниц, которые нам нужны, например:
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 ) ;
}
Для Android вся заслуга принадлежит Кристиану Холдуну и Зибе Брауэру за реализацию идеи PopupWindow
, а для расчета высоты клавиатуры я просто перенес ее в систему модулей React Native.