rn: refactor BottomSheet

Avoid using a Modal since those create trouble with the view hierarchy.
This commit is contained in:
Saúl Ibarra Corretgé 2019-04-24 13:05:14 +02:00 committed by Zoltan Bettenbuk
parent 89719520e2
commit 70dc22c107
3 changed files with 29 additions and 62 deletions

View File

@ -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();
} }
} }

View File

@ -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)'
} }
}); });

View File

@ -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>