Skip to content

Instantly share code, notes, and snippets.

@lubaochuan
Created March 7, 2021 22:06
Show Gist options
  • Save lubaochuan/8f76070ffeb958370ec00f4b03454d8c to your computer and use it in GitHub Desktop.
Save lubaochuan/8f76070ffeb958370ec00f4b03454d8c to your computer and use it in GitHub Desktop.
import {
BackHandler,
LayoutAnimation,
Platform,
UIManager,
View,
} from 'react-native';
import PropTypes from 'prop-types';
import React from 'react';
import { isIphoneX } from 'react-native-iphone-x-helper';
if (
Platform.OS === 'android' &&
UIManager.setLayoutAnimationEnabledExperimental
) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
export const INPUT_METHOD = {
NONE: 'NONE',
KEYBOARD: 'KEYBOARD',
CUSTOM: 'CUSTOM',
};
export default class MessagingContainer extends React.Component {
static propTypes = {
children: PropTypes.node,
containerHeight: PropTypes.number.isRequired,
contentHeight: PropTypes.number.isRequired,
keyboardHeight: PropTypes.number.isRequired,
keyboardVisible: PropTypes.bool.isRequired,
keyboardWillShow: PropTypes.bool.isRequired,
keyboardWillHide: PropTypes.bool.isRequired,
keyboardAnimationDuration: PropTypes.number.isRequired,
inputMethod: PropTypes.oneOf(Object.values(INPUT_METHOD))
.isRequired,
onChangeInputMethod: PropTypes.func,
renderInputMethodEditor: PropTypes.func.isRequired,
};
static defaultProps = {
children: null,
onChangeInputMethod: () => {},
};
componentDidMount() {
this.subscription = BackHandler.addEventListener(
'hardwareBackPress',
() => {
const { onChangeInputMethod, inputMethod } = this.props;
if (inputMethod === INPUT_METHOD.CUSTOM) {
onChangeInputMethod(INPUT_METHOD.NONE);
return true;
}
return false;
},
);
}
componentWillUnmount() {
this.subscription.remove();
}
componentDidUpdate(prevProps) {
const { onChangeInputMethod } = this.props;
if (this.props.keyboardVisible && !prevProps.keyboardVisible) {
// Keyboard shown
onChangeInputMethod(INPUT_METHOD.KEYBOARD);
} else if (
// Keyboard hidden
!this.props.keyboardVisible &&
prevProps.keyboardVisible &&
this.props.inputMethod !== INPUT_METHOD.CUSTOM
) {
onChangeInputMethod(INPUT_METHOD.NONE);
}
const { keyboardAnimationDuration } = this.props;
// Animate between states
const animation = LayoutAnimation.create(
keyboardAnimationDuration,
Platform.OS === 'android'
? LayoutAnimation.Types.easeInEaseOut
: LayoutAnimation.Types.keyboard,
LayoutAnimation.Properties.opacity,
);
LayoutAnimation.configureNext(animation);
}
render() {
const {
children,
renderInputMethodEditor,
inputMethod,
containerHeight,
contentHeight,
keyboardHeight,
keyboardWillShow,
keyboardWillHide,
} = this.props;
const useContentHeight =
keyboardWillShow || inputMethod === INPUT_METHOD.KEYBOARD;
const containerStyle = {
height: useContentHeight ? contentHeight : containerHeight,
};
const showCustomInput =
inputMethod === INPUT_METHOD.CUSTOM && !keyboardWillShow;
const keyboardIsHidden =
inputMethod === INPUT_METHOD.NONE && !keyboardWillShow;
const keyboardIsHiding =
inputMethod === INPUT_METHOD.KEYBOARD && keyboardWillHide;
const inputStyle = {
height: showCustomInput ? keyboardHeight || 250 : 0,
marginTop:
isIphoneX() && (keyboardIsHidden || keyboardIsHiding)
? 24
: 0,
};
return (
<View style={containerStyle}>
{children}
<View style={inputStyle}>{renderInputMethodEditor()}</View>
</View>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment