This library will address these problems:
-
When set windowSoftInputMode to
adjustNothing
, the React Native Keyboard events,keyboardDidHide
andkeyboardDidShow
, will stop working (see issue #2852). -
When Keyboard appear the entire app content will move up (iOS and Android).
-
For chat application than needs to keep the bottom text input in the same position when dismiss the Keyboard and show some actions, the switch will not be that smooth.
$ yarn add react-native-keyboard-area
Is recommend to use React Native > 0.60, the autolinking will install this library native RNKeyboard
module for iOS and Android.
-
On iOS: React Native provides a component called
KeyboardAvoidingView
, wrap your page with that and it will move up the content when the keyboard appears. -
On Android: By default in the AndroidManifest.xml we have the windowSoftInputMode set to
adjustResize
, the entire app content will move up when the keyboard appears so we don't need theKeyboardAvoidingView
component.
In both way, the entire page content will move up or down then the Keyboard appear or disappear.
But sometimes we don't need to whole app to move up, the most common example is a Chat application, we might want to switch to a Custom View when the keyboard disappear.
This library solve the problem by creating a wrapper component KeyboardArea
, this component will adjust his height then the keyboard appear or disappear.
In addition is also possible to control the state with isOpen
props or with the exposed open()
and close()
methods.
Another benefit is that the ReactNaive will not repaint the whole app when the keyboard appears since main view will not change is size.
This library have some iOS and Android native code to notify, through an event named KeyboardSizeChanges
, the KeyboardArea
component when the keyboard height changes.
-
On iOS we just use the
UIResponder
keyboardWillShowNotification and keyboardWillHideNotification to then emit the event with the current height. -
On Android we need to set the windowSoftInputMode to
adjustNothing
, to avoid the keyboard to move up the entire view, then we create a invisiblePopupWindow
to listen the layout changes and measure the keyboard height.
Most of the logic is inside the KeyboardArea
component, we just need to wrap the content we want to show when the keyboard disappear and then set the isOpen props when we need to show, in follow example case, the ChatActionsInput component.
** this is a simplified version of the above screenshots **
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>
);
}
Since on android we might want use adjustResize for the others page, we can use this library setWindowSoftInputMode
to dynamically change the SoftInput mode only for the pages that we need, for example:
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);
}
For Android all credits goes to Cristian Holdunu and Siebe Brouwer for the PopupWindow
idea implementation and to calculate the keyboard height, I just port it in the React Native module system.