react-native/local-cli/templates/HelloNavigation/components/KeyboardSpacer.js

121 lines
3.1 KiB
JavaScript

/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
'use strict';
/* @flow */
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {Platform, View, Keyboard, LayoutAnimation} from 'react-native';
type Props = {
offset?: number,
};
type State = {
keyboardHeight: number,
};
// Consider contributing this to the popular library:
// https://github.com/Andr3wHur5t/react-native-keyboard-spacer
/**
* On iOS, the software keyboard covers the screen by default.
* This is not desirable if there are TextInputs near the bottom of the screen -
* they would be covered by the keyboard and the user cannot see what they
* are typing.
* To get around this problem, place a `<KeyboardSpacer />` at the bottom
* of the screen, after your TextInputs. The keyboard spacer has size 0 and
* when the keyboard is shown it will grow to the same size as the keyboard,
* shifting all views above it and therefore making them visible.
*
* On Android, this component is not needed because resizing the UI when
* the keyboard is shown is supported by the OS.
* Simply set the `android:windowSoftInputMode="adjustResize"` attribute
* on the <activity> element in your AndroidManifest.xml.
*
* How is this different from KeyboardAvoidingView?
* The KeyboardAvoidingView doesn't work when used together with
* a ScrollView/ListView.
*/
const KeyboardSpacer = () =>
Platform.OS === 'ios' ? <KeyboardSpacerIOS /> : null;
class KeyboardSpacerIOS extends Component<Props, State> {
static propTypes = {
offset: PropTypes.number,
};
static defaultProps = {
offset: 0,
};
state: State = {
keyboardHeight: 0,
};
UNSAFE_componentWillMount() {
this._registerEvents();
}
componentWillUnmount() {
this._unRegisterEvents();
}
_keyboardWillShowSubscription: {+remove: Function};
_keyboardWillHideSubscription: {+remove: Function};
_registerEvents = () => {
this._keyboardWillShowSubscription = Keyboard.addListener(
'keyboardWillShow',
this._keyboardWillShow,
);
this._keyboardWillHideSubscription = Keyboard.addListener(
'keyboardWillHide',
this._keyboardWillHide,
);
};
_unRegisterEvents = () => {
this._keyboardWillShowSubscription.remove();
this._keyboardWillHideSubscription.remove();
};
_configureLayoutAnimation = () => {
// Any duration is OK here. The `type: 'keyboard defines the animation.
LayoutAnimation.configureNext({
duration: 100,
update: {
type: 'keyboard',
},
});
};
_keyboardWillShow = (e: any) => {
this._configureLayoutAnimation();
this.setState({
keyboardHeight: e.endCoordinates.height - (this.props.offset || 0),
});
};
_keyboardWillHide = () => {
this._configureLayoutAnimation();
this.setState({
keyboardHeight: 0,
});
};
render() {
return <View style={{height: this.state.keyboardHeight}} />;
}
}
export default KeyboardSpacer;