rn: refactor BottomSheet
Avoid using a Modal since those create trouble with the view hierarchy.
This commit is contained in:
parent
89719520e2
commit
70dc22c107
|
@ -1,10 +1,10 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import React, { Component, type Node } from 'react';
|
import React, { PureComponent, type Node } from 'react';
|
||||||
import { TouchableWithoutFeedback, View } from 'react-native';
|
import { SafeAreaView, View } from 'react-native';
|
||||||
|
|
||||||
import { ColorSchemeRegistry } from '../../../color-scheme';
|
import { ColorSchemeRegistry } from '../../../color-scheme';
|
||||||
import { Modal } from '../../../react';
|
import { SlidingView } from '../../../react';
|
||||||
import { connect } from '../../../redux';
|
import { connect } from '../../../redux';
|
||||||
import { StyleType } from '../../../styles';
|
import { StyleType } from '../../../styles';
|
||||||
|
|
||||||
|
@ -33,19 +33,22 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A component emulating Android's BottomSheet. For all intents and purposes,
|
* A component emulating Android's BottomSheet.
|
||||||
* this component has been designed to work and behave as a {@code Dialog}.
|
|
||||||
*/
|
*/
|
||||||
class BottomSheet extends Component<Props> {
|
class BottomSheet extends PureComponent<Props> {
|
||||||
/**
|
/**
|
||||||
* Initializes a new {@code BottomSheet} instance.
|
* Assembles a style for the BottomSheet container.
|
||||||
*
|
*
|
||||||
* @inheritdoc
|
* @private
|
||||||
|
* @returns {StyleType}
|
||||||
*/
|
*/
|
||||||
constructor(props: Props) {
|
_getContainerStyle() {
|
||||||
super(props);
|
const { _styles } = this.props;
|
||||||
|
|
||||||
this._onCancel = this._onCancel.bind(this);
|
return {
|
||||||
|
...styles.container,
|
||||||
|
backgroundColor: _styles.sheet.backgroundColor
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,39 +60,19 @@ class BottomSheet extends Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
const { _styles } = this.props;
|
const { _styles } = this.props;
|
||||||
|
|
||||||
return [
|
return (
|
||||||
<View
|
<SlidingView
|
||||||
key = 'overlay'
|
onHide = { this.props.onCancel }
|
||||||
style = { styles.overlay } />,
|
position = 'bottom'
|
||||||
<Modal
|
show = { true }>
|
||||||
key = 'modal'
|
<SafeAreaView
|
||||||
onRequestClose = { this._onCancel }
|
style = { this._getContainerStyle() }>
|
||||||
visible = { true }>
|
|
||||||
<View style = { styles.container }>
|
|
||||||
<TouchableWithoutFeedback
|
|
||||||
onPress = { this._onCancel } >
|
|
||||||
<View style = { styles.backdrop } />
|
|
||||||
</TouchableWithoutFeedback>
|
|
||||||
<View style = { _styles.sheet }>
|
<View style = { _styles.sheet }>
|
||||||
{ this.props.children }
|
{ this.props.children }
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</SafeAreaView>
|
||||||
</Modal>
|
</SlidingView>
|
||||||
];
|
);
|
||||||
}
|
|
||||||
|
|
||||||
_onCancel: () => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels the dialog by calling the onCancel prop callback.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_onCancel() {
|
|
||||||
const { onCancel } = this.props;
|
|
||||||
|
|
||||||
onCancel && onCancel();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,31 +28,14 @@ export const PLACEHOLDER_COLOR = ColorPalette.lightGrey;
|
||||||
* {@link https://material.io/guidelines/components/bottom-sheets.html}.
|
* {@link https://material.io/guidelines/components/bottom-sheets.html}.
|
||||||
*/
|
*/
|
||||||
export const bottomSheetStyles = createStyleSheet({
|
export const bottomSheetStyles = createStyleSheet({
|
||||||
/**
|
|
||||||
* Style for a backdrop which dims the view in the background. This view
|
|
||||||
* will also be clickable. The backgroundColor is applied to the overlay
|
|
||||||
* view instead, so the modal animation doesn't affect the backdrop.
|
|
||||||
*/
|
|
||||||
backdrop: {
|
|
||||||
...StyleSheet.absoluteFillObject
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Style for the container of the sheet.
|
* Style for the container of the sheet.
|
||||||
*/
|
*/
|
||||||
container: {
|
container: {
|
||||||
alignItems: 'flex-end',
|
bottom: 0,
|
||||||
flex: 1,
|
left: 0,
|
||||||
flexDirection: 'row',
|
position: 'absolute',
|
||||||
justifyContent: 'center'
|
right: 0
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Style for an overlay on top of which the sheet will be displayed.
|
|
||||||
*/
|
|
||||||
overlay: {
|
|
||||||
...StyleSheet.absoluteFillObject,
|
|
||||||
backgroundColor: 'rgba(127, 127, 127, 0.6)'
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,7 @@ export default class SlidingView extends PureComponent<Props, State> {
|
||||||
<View style = { styles.sliderViewShadow } />
|
<View style = { styles.sliderViewShadow } />
|
||||||
</TouchableWithoutFeedback>
|
</TouchableWithoutFeedback>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
|
pointerEvents = 'box-none'
|
||||||
style = { this._getContentStyle() }>
|
style = { this._getContentStyle() }>
|
||||||
{ this.props.children }
|
{ this.props.children }
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
|
|
Loading…
Reference in New Issue