mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add e2e test for a Modal component
Summary: Changelog: [General][Added] - [RNTester] Added a modal component example with onShow/onDismiss callbacks Reviewed By: lunaleaps Differential Revision: D27926745 fbshipit-source-id: c2f2b8a15154a090bb747bb02cdf428e90861824
This commit is contained in:
committed by
Facebook GitHub Bot
parent
7310847758
commit
23ae702d97
@@ -0,0 +1,343 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Modal,
|
||||
Picker,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Switch,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
ScrollView,
|
||||
} from 'react-native';
|
||||
import type {RNTesterExampleModuleItem} from '../../types/RNTesterTypes';
|
||||
|
||||
const Item = Picker.Item;
|
||||
|
||||
class Button extends React.Component<$FlowFixMeProps, $FlowFixMeState> {
|
||||
state = {
|
||||
active: false,
|
||||
};
|
||||
|
||||
_onHighlight = () => {
|
||||
this.setState({active: true});
|
||||
};
|
||||
|
||||
_onUnhighlight = () => {
|
||||
this.setState({active: false});
|
||||
};
|
||||
|
||||
render() {
|
||||
const colorStyle = {
|
||||
color: this.state.active ? '#fff' : '#000',
|
||||
};
|
||||
return (
|
||||
<TouchableHighlight
|
||||
onHideUnderlay={this._onUnhighlight}
|
||||
onPress={this.props.onPress}
|
||||
onShowUnderlay={this._onHighlight}
|
||||
style={[styles.button, this.props.style]}
|
||||
underlayColor="#a9d9d4">
|
||||
<Text style={[styles.buttonText, colorStyle]}>
|
||||
{this.props.children}
|
||||
</Text>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const supportedOrientationsPickerValues = [
|
||||
['portrait'],
|
||||
['landscape'],
|
||||
['landscape-left'],
|
||||
['portrait', 'landscape-right'],
|
||||
['portrait', 'landscape'],
|
||||
[],
|
||||
];
|
||||
|
||||
class ModalExample extends React.Component<{...}, $FlowFixMe> {
|
||||
state: $FlowFixMe = {
|
||||
animationType: 'none',
|
||||
modalVisible: false,
|
||||
transparent: false,
|
||||
hardwareAccelerated: false,
|
||||
statusBarTranslucent: false,
|
||||
presentationStyle: 'fullScreen',
|
||||
selectedSupportedOrientation: '0',
|
||||
currentOrientation: 'unknown',
|
||||
action: '',
|
||||
};
|
||||
|
||||
_setModalVisible = visible => {
|
||||
this.setState({modalVisible: visible});
|
||||
};
|
||||
|
||||
_setAnimationType = type => {
|
||||
this.setState({animationType: type});
|
||||
};
|
||||
|
||||
_toggleTransparent = () => {
|
||||
this.setState({transparent: !this.state.transparent});
|
||||
};
|
||||
|
||||
_toggleHardwareAccelerated = () => {
|
||||
this.setState({hardwareAccelerated: !this.state.hardwareAccelerated});
|
||||
};
|
||||
|
||||
_toggleStatusBarTranslucent = () => {
|
||||
this.setState({statusBarTranslucent: !this.state.statusBarTranslucent});
|
||||
};
|
||||
|
||||
renderSwitch(): React.Node {
|
||||
if (Platform.isTV) {
|
||||
return null;
|
||||
}
|
||||
if (Platform.OS === 'android') {
|
||||
return (
|
||||
<>
|
||||
<Text style={styles.rowTitle}>Hardware Accelerated</Text>
|
||||
<Switch
|
||||
value={this.state.hardwareAccelerated}
|
||||
onValueChange={this._toggleHardwareAccelerated}
|
||||
/>
|
||||
<Text style={styles.rowTitle}>Status Bar Translucent</Text>
|
||||
<Switch
|
||||
value={this.state.statusBarTranslucent}
|
||||
onValueChange={this._toggleStatusBarTranslucent}
|
||||
/>
|
||||
<Text style={styles.rowTitle}>Transparent</Text>
|
||||
<Switch
|
||||
value={this.state.transparent}
|
||||
onValueChange={this._toggleTransparent}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Switch
|
||||
value={this.state.transparent}
|
||||
onValueChange={this._toggleTransparent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render(): React.Node {
|
||||
const modalBackgroundStyle = {
|
||||
backgroundColor: this.state.transparent
|
||||
? 'rgba(0, 0, 0, 0.5)'
|
||||
: '#f5fcff',
|
||||
};
|
||||
const innerContainerTransparentStyle = this.state.transparent
|
||||
? {backgroundColor: '#fff', padding: 20}
|
||||
: null;
|
||||
const activeButtonStyle = {
|
||||
backgroundColor: '#ddd',
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollView contentContainerStyle={styles.ScrollView}>
|
||||
<Modal
|
||||
animationType={this.state.animationType}
|
||||
presentationStyle={this.state.presentationStyle}
|
||||
transparent={this.state.transparent}
|
||||
hardwareAccelerated={this.state.hardwareAccelerated}
|
||||
statusBarTranslucent={this.state.statusBarTranslucent}
|
||||
visible={this.state.modalVisible}
|
||||
onRequestClose={() => this._setModalVisible(false)}
|
||||
supportedOrientations={
|
||||
supportedOrientationsPickerValues[
|
||||
Number(this.state.selectedSupportedOrientation)
|
||||
]
|
||||
}
|
||||
onOrientationChange={evt =>
|
||||
this.setState({currentOrientation: evt.nativeEvent.orientation})
|
||||
}
|
||||
onDismiss={() => {
|
||||
if (this.state.action === 'onDismiss') {
|
||||
alert(this.state.action);
|
||||
}
|
||||
}}
|
||||
onShow={() => {
|
||||
if (this.state.action === 'onShow') {
|
||||
alert(this.state.action);
|
||||
}
|
||||
}}>
|
||||
<View style={[styles.container, modalBackgroundStyle]}>
|
||||
<View
|
||||
style={[styles.innerContainer, innerContainerTransparentStyle]}>
|
||||
<Text>
|
||||
This modal was presented{' '}
|
||||
{this.state.animationType === 'none' ? 'without' : 'with'}{' '}
|
||||
animation.
|
||||
</Text>
|
||||
<Text>
|
||||
It is currently displayed in {this.state.currentOrientation}{' '}
|
||||
mode.
|
||||
</Text>
|
||||
<Button
|
||||
onPress={this._setModalVisible.bind(this, false)}
|
||||
style={styles.modalButton}>
|
||||
Close
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
<View style={styles.row}>
|
||||
<Text style={styles.rowTitle}>Animation Type</Text>
|
||||
<Button
|
||||
onPress={this._setAnimationType.bind(this, 'none')}
|
||||
style={
|
||||
this.state.animationType === 'none' ? activeButtonStyle : {}
|
||||
}>
|
||||
none
|
||||
</Button>
|
||||
<Button
|
||||
onPress={this._setAnimationType.bind(this, 'slide')}
|
||||
style={
|
||||
this.state.animationType === 'slide' ? activeButtonStyle : {}
|
||||
}>
|
||||
slide
|
||||
</Button>
|
||||
<Button
|
||||
onPress={this._setAnimationType.bind(this, 'fade')}
|
||||
style={
|
||||
this.state.animationType === 'fade' ? activeButtonStyle : {}
|
||||
}>
|
||||
fade
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
<View style={styles.row}>{this.renderSwitch()}</View>
|
||||
{this.renderPickers()}
|
||||
<Button onPress={this._setModalVisible.bind(this, true)}>
|
||||
Present
|
||||
</Button>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
renderPickers(): React.Node {
|
||||
if (Platform.isTV) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<View>
|
||||
<View>
|
||||
<Text style={styles.rowTitle}>Presentation style</Text>
|
||||
<Picker
|
||||
selectedValue={this.state.presentationStyle}
|
||||
onValueChange={presentationStyle =>
|
||||
this.setState({presentationStyle})
|
||||
}
|
||||
itemStyle={styles.pickerItem}>
|
||||
<Item label="Full Screen" value="fullScreen" />
|
||||
<Item label="Page Sheet" value="pageSheet" />
|
||||
<Item label="Form Sheet" value="formSheet" />
|
||||
<Item label="Over Full Screen" value="overFullScreen" />
|
||||
<Item label="Default presentationStyle" value={null} />
|
||||
</Picker>
|
||||
</View>
|
||||
|
||||
<View>
|
||||
<Text style={styles.rowTitle}>Supported orientations</Text>
|
||||
<Picker
|
||||
selectedValue={this.state.selectedSupportedOrientation}
|
||||
onValueChange={(_, i) =>
|
||||
this.setState({selectedSupportedOrientation: i.toString()})
|
||||
}
|
||||
itemStyle={styles.pickerItem}>
|
||||
<Item label="Portrait" value={'0'} />
|
||||
<Item label="Landscape" value={'1'} />
|
||||
<Item label="Landscape left" value={'2'} />
|
||||
<Item label="Portrait and landscape right" value={'3'} />
|
||||
<Item label="Portrait and landscape" value={'4'} />
|
||||
<Item label="Default supportedOrientations" value={'5'} />
|
||||
</Picker>
|
||||
</View>
|
||||
|
||||
<View>
|
||||
<Text style={styles.rowTitle}>Actions</Text>
|
||||
{Platform.OS === 'ios' ? (
|
||||
<Picker
|
||||
selectedValue={this.state.action}
|
||||
onValueChange={action => this.setState({action})}
|
||||
itemStyle={styles.pickerItem}>
|
||||
<Item label="None" value="" />
|
||||
<Item label="On Dismiss" value="onDismiss" />
|
||||
<Item label="On Show" value="onShow" />
|
||||
</Picker>
|
||||
) : (
|
||||
<Picker
|
||||
selectedValue={this.state.action}
|
||||
onValueChange={action => this.setState({action})}
|
||||
itemStyle={styles.pickerItem}>
|
||||
<Item label="None" value="" />
|
||||
<Item label="On Show" value="onShow" />
|
||||
</Picker>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
padding: 20,
|
||||
},
|
||||
innerContainer: {
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
},
|
||||
row: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginBottom: 20,
|
||||
},
|
||||
rowTitle: {
|
||||
flex: 1,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
button: {
|
||||
borderRadius: 5,
|
||||
flexGrow: 1,
|
||||
height: 44,
|
||||
alignSelf: 'stretch',
|
||||
justifyContent: 'center',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
buttonText: {
|
||||
fontSize: 18,
|
||||
margin: 5,
|
||||
textAlign: 'center',
|
||||
},
|
||||
modalButton: {
|
||||
marginTop: 10,
|
||||
},
|
||||
pickerItem: {
|
||||
fontSize: 16,
|
||||
},
|
||||
ScrollView: {
|
||||
paddingTop: 10,
|
||||
paddingBottom: 100,
|
||||
},
|
||||
});
|
||||
|
||||
export default ({
|
||||
title: 'Modal Presentation',
|
||||
name: 'basic',
|
||||
description: 'Modals can be presented with or without animation',
|
||||
render: (): React.Node => <ModalExample />,
|
||||
}: RNTesterExampleModuleItem);
|
||||
@@ -4,347 +4,21 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import ModalCustomizable from './ModalCustomizable';
|
||||
import ModalOnShow from './ModalOnShow';
|
||||
import type {RNTesterExampleModuleItem} from '../../types/RNTesterTypes';
|
||||
|
||||
const React = require('react');
|
||||
|
||||
const {
|
||||
Modal,
|
||||
Picker,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Switch,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
ScrollView,
|
||||
} = require('react-native');
|
||||
|
||||
const Item = Picker.Item;
|
||||
|
||||
exports.displayName = (undefined: ?string);
|
||||
exports.framework = 'React';
|
||||
exports.title = 'Modal';
|
||||
exports.category = 'UI';
|
||||
exports.documentationURL = 'https://reactnative.dev/docs/modal';
|
||||
exports.description = 'Component for presenting modal views.';
|
||||
|
||||
class Button extends React.Component<$FlowFixMeProps, $FlowFixMeState> {
|
||||
state = {
|
||||
active: false,
|
||||
};
|
||||
|
||||
_onHighlight = () => {
|
||||
this.setState({active: true});
|
||||
};
|
||||
|
||||
_onUnhighlight = () => {
|
||||
this.setState({active: false});
|
||||
};
|
||||
|
||||
render() {
|
||||
const colorStyle = {
|
||||
color: this.state.active ? '#fff' : '#000',
|
||||
};
|
||||
return (
|
||||
<TouchableHighlight
|
||||
onHideUnderlay={this._onUnhighlight}
|
||||
onPress={this.props.onPress}
|
||||
onShowUnderlay={this._onHighlight}
|
||||
style={[styles.button, this.props.style]}
|
||||
underlayColor="#a9d9d4">
|
||||
<Text style={[styles.buttonText, colorStyle]}>
|
||||
{this.props.children}
|
||||
</Text>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const supportedOrientationsPickerValues = [
|
||||
['portrait'],
|
||||
['landscape'],
|
||||
['landscape-left'],
|
||||
['portrait', 'landscape-right'],
|
||||
['portrait', 'landscape'],
|
||||
[],
|
||||
];
|
||||
|
||||
class ModalExample extends React.Component<{...}, $FlowFixMeState> {
|
||||
state = {
|
||||
animationType: 'none',
|
||||
modalVisible: false,
|
||||
transparent: false,
|
||||
hardwareAccelerated: false,
|
||||
statusBarTranslucent: false,
|
||||
presentationStyle: 'fullScreen',
|
||||
selectedSupportedOrientation: '0',
|
||||
currentOrientation: 'unknown',
|
||||
action: '',
|
||||
};
|
||||
|
||||
_setModalVisible = visible => {
|
||||
this.setState({modalVisible: visible});
|
||||
};
|
||||
|
||||
_setAnimationType = type => {
|
||||
this.setState({animationType: type});
|
||||
};
|
||||
|
||||
_toggleTransparent = () => {
|
||||
this.setState({transparent: !this.state.transparent});
|
||||
};
|
||||
|
||||
_toggleHardwareAccelerated = () => {
|
||||
this.setState({hardwareAccelerated: !this.state.hardwareAccelerated});
|
||||
};
|
||||
|
||||
_toggleStatusBarTranslucent = () => {
|
||||
this.setState({statusBarTranslucent: !this.state.statusBarTranslucent});
|
||||
};
|
||||
|
||||
renderSwitch() {
|
||||
if (Platform.isTV) {
|
||||
return null;
|
||||
}
|
||||
if (Platform.OS === 'android') {
|
||||
return (
|
||||
<>
|
||||
<Text style={styles.rowTitle}>Hardware Accelerated</Text>
|
||||
<Switch
|
||||
value={this.state.hardwareAccelerated}
|
||||
onValueChange={this._toggleHardwareAccelerated}
|
||||
/>
|
||||
<Text style={styles.rowTitle}>Status Bar Translucent</Text>
|
||||
<Switch
|
||||
value={this.state.statusBarTranslucent}
|
||||
onValueChange={this._toggleStatusBarTranslucent}
|
||||
/>
|
||||
<Text style={styles.rowTitle}>Transparent</Text>
|
||||
<Switch
|
||||
value={this.state.transparent}
|
||||
onValueChange={this._toggleTransparent}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Switch
|
||||
value={this.state.transparent}
|
||||
onValueChange={this._toggleTransparent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const modalBackgroundStyle = {
|
||||
backgroundColor: this.state.transparent
|
||||
? 'rgba(0, 0, 0, 0.5)'
|
||||
: '#f5fcff',
|
||||
};
|
||||
const innerContainerTransparentStyle = this.state.transparent
|
||||
? {backgroundColor: '#fff', padding: 20}
|
||||
: null;
|
||||
const activeButtonStyle = {
|
||||
backgroundColor: '#ddd',
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollView contentContainerStyle={styles.ScrollView}>
|
||||
<Modal
|
||||
animationType={this.state.animationType}
|
||||
presentationStyle={this.state.presentationStyle}
|
||||
transparent={this.state.transparent}
|
||||
hardwareAccelerated={this.state.hardwareAccelerated}
|
||||
statusBarTranslucent={this.state.statusBarTranslucent}
|
||||
visible={this.state.modalVisible}
|
||||
onRequestClose={() => this._setModalVisible(false)}
|
||||
supportedOrientations={
|
||||
supportedOrientationsPickerValues[
|
||||
Number(this.state.selectedSupportedOrientation)
|
||||
]
|
||||
}
|
||||
onOrientationChange={evt =>
|
||||
this.setState({currentOrientation: evt.nativeEvent.orientation})
|
||||
}
|
||||
onDismiss={() => {
|
||||
if (this.state.action === 'onDismiss') alert(this.state.action);
|
||||
}}
|
||||
onShow={() => {
|
||||
if (this.state.action === 'onShow') alert(this.state.action);
|
||||
}}>
|
||||
<View style={[styles.container, modalBackgroundStyle]}>
|
||||
<View
|
||||
style={[styles.innerContainer, innerContainerTransparentStyle]}>
|
||||
<Text>
|
||||
This modal was presented{' '}
|
||||
{this.state.animationType === 'none' ? 'without' : 'with'}{' '}
|
||||
animation.
|
||||
</Text>
|
||||
<Text>
|
||||
It is currently displayed in {this.state.currentOrientation}{' '}
|
||||
mode.
|
||||
</Text>
|
||||
<Button
|
||||
onPress={this._setModalVisible.bind(this, false)}
|
||||
style={styles.modalButton}>
|
||||
Close
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
<View style={styles.row}>
|
||||
<Text style={styles.rowTitle}>Animation Type</Text>
|
||||
<Button
|
||||
onPress={this._setAnimationType.bind(this, 'none')}
|
||||
style={
|
||||
this.state.animationType === 'none' ? activeButtonStyle : {}
|
||||
}>
|
||||
none
|
||||
</Button>
|
||||
<Button
|
||||
onPress={this._setAnimationType.bind(this, 'slide')}
|
||||
style={
|
||||
this.state.animationType === 'slide' ? activeButtonStyle : {}
|
||||
}>
|
||||
slide
|
||||
</Button>
|
||||
<Button
|
||||
onPress={this._setAnimationType.bind(this, 'fade')}
|
||||
style={
|
||||
this.state.animationType === 'fade' ? activeButtonStyle : {}
|
||||
}>
|
||||
fade
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
<View style={styles.row}>{this.renderSwitch()}</View>
|
||||
{this.renderPickers()}
|
||||
<Button onPress={this._setModalVisible.bind(this, true)}>
|
||||
Present
|
||||
</Button>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
renderPickers() {
|
||||
if (Platform.isTV) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<View>
|
||||
<View>
|
||||
<Text style={styles.rowTitle}>Presentation style</Text>
|
||||
<Picker
|
||||
selectedValue={this.state.presentationStyle}
|
||||
onValueChange={presentationStyle =>
|
||||
this.setState({presentationStyle})
|
||||
}
|
||||
itemStyle={styles.pickerItem}>
|
||||
<Item label="Full Screen" value="fullScreen" />
|
||||
<Item label="Page Sheet" value="pageSheet" />
|
||||
<Item label="Form Sheet" value="formSheet" />
|
||||
<Item label="Over Full Screen" value="overFullScreen" />
|
||||
<Item label="Default presentationStyle" value={null} />
|
||||
</Picker>
|
||||
</View>
|
||||
|
||||
<View>
|
||||
<Text style={styles.rowTitle}>Supported orientations</Text>
|
||||
<Picker
|
||||
selectedValue={this.state.selectedSupportedOrientation}
|
||||
onValueChange={(_, i) =>
|
||||
this.setState({selectedSupportedOrientation: i.toString()})
|
||||
}
|
||||
itemStyle={styles.pickerItem}>
|
||||
<Item label="Portrait" value={'0'} />
|
||||
<Item label="Landscape" value={'1'} />
|
||||
<Item label="Landscape left" value={'2'} />
|
||||
<Item label="Portrait and landscape right" value={'3'} />
|
||||
<Item label="Portrait and landscape" value={'4'} />
|
||||
<Item label="Default supportedOrientations" value={'5'} />
|
||||
</Picker>
|
||||
</View>
|
||||
|
||||
<View>
|
||||
<Text style={styles.rowTitle}>Actions</Text>
|
||||
{Platform.OS === 'ios' ? (
|
||||
<Picker
|
||||
selectedValue={this.state.action}
|
||||
onValueChange={action => this.setState({action})}
|
||||
itemStyle={styles.pickerItem}>
|
||||
<Item label="None" value="" />
|
||||
<Item label="On Dismiss" value="onDismiss" />
|
||||
<Item label="On Show" value="onShow" />
|
||||
</Picker>
|
||||
) : (
|
||||
<Picker
|
||||
selectedValue={this.state.action}
|
||||
onValueChange={action => this.setState({action})}
|
||||
itemStyle={styles.pickerItem}>
|
||||
<Item label="None" value="" />
|
||||
<Item label="On Show" value="onShow" />
|
||||
</Picker>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Modal Presentation',
|
||||
name: 'basic',
|
||||
description: 'Modals can be presented with or without animation',
|
||||
render: (): React.Node => <ModalExample />,
|
||||
},
|
||||
];
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
padding: 20,
|
||||
},
|
||||
innerContainer: {
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
},
|
||||
row: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginBottom: 20,
|
||||
},
|
||||
rowTitle: {
|
||||
flex: 1,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
button: {
|
||||
borderRadius: 5,
|
||||
flexGrow: 1,
|
||||
height: 44,
|
||||
alignSelf: 'stretch',
|
||||
justifyContent: 'center',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
buttonText: {
|
||||
fontSize: 18,
|
||||
margin: 5,
|
||||
textAlign: 'center',
|
||||
},
|
||||
modalButton: {
|
||||
marginTop: 10,
|
||||
},
|
||||
pickerItem: {
|
||||
fontSize: 16,
|
||||
},
|
||||
ScrollView: {
|
||||
paddingTop: 10,
|
||||
paddingBottom: 100,
|
||||
},
|
||||
});
|
||||
export const displayName = (undefined: ?string);
|
||||
export const framework = 'React';
|
||||
export const title = 'Modal';
|
||||
export const category = 'UI';
|
||||
export const documentationURL = 'https://reactnative.dev/docs/modal';
|
||||
export const description = 'Component for presenting modal views.';
|
||||
export const examples = ([
|
||||
ModalCustomizable,
|
||||
ModalOnShow,
|
||||
]: Array<RNTesterExampleModuleItem>);
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import {Modal, Pressable, StyleSheet, Text, View} from 'react-native';
|
||||
import type {RNTesterExampleModuleItem} from '../../types/RNTesterTypes';
|
||||
|
||||
function ModalOnShowOnDismiss(): React.Node {
|
||||
const [modalVisible, setModalVisible] = React.useState(false);
|
||||
const [onShowCount, setOnShowCount] = React.useState(0);
|
||||
const [onDismissCount, setOnDismissCount] = React.useState(0);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Modal
|
||||
animationType="slide"
|
||||
transparent={true}
|
||||
visible={modalVisible}
|
||||
onShow={() => {
|
||||
setOnShowCount(onShowCount + 1);
|
||||
}}
|
||||
onDismiss={() => {
|
||||
setOnDismissCount(onDismissCount + 1);
|
||||
}}
|
||||
onRequestClose={() => {
|
||||
setModalVisible(false);
|
||||
}}>
|
||||
<View style={[styles.centeredView, styles.modalBackdrop]}>
|
||||
<View style={styles.modalView}>
|
||||
<Text testID="modal-on-show-count">
|
||||
onShow is called {onShowCount} times
|
||||
</Text>
|
||||
<Text testID="modal-on-dismiss-count">
|
||||
onDismiss is called {onDismissCount} times
|
||||
</Text>
|
||||
<Pressable
|
||||
style={[styles.button, styles.buttonClose]}
|
||||
onPress={() => setModalVisible(false)}>
|
||||
<Text testID="dismiss-modal" style={styles.textStyle}>
|
||||
Hide Modal
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
</Modal>
|
||||
<Text testID="on-show-count">onShow is called {onShowCount} times</Text>
|
||||
<Text testID="on-dismiss-count">
|
||||
onDismiss is called {onDismissCount} times
|
||||
</Text>
|
||||
<Pressable
|
||||
style={[styles.button, styles.buttonOpen]}
|
||||
onPress={() => setModalVisible(true)}>
|
||||
<Text testID="open-modal" style={styles.textStyle}>
|
||||
Show Modal
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
paddingVertical: 30,
|
||||
},
|
||||
centeredView: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
modalBackdrop: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
modalView: {
|
||||
margin: 20,
|
||||
backgroundColor: 'white',
|
||||
borderRadius: 20,
|
||||
padding: 35,
|
||||
alignItems: 'center',
|
||||
shadowColor: '#000',
|
||||
shadowOffset: {
|
||||
width: 0,
|
||||
height: 2,
|
||||
},
|
||||
shadowOpacity: 0.25,
|
||||
shadowRadius: 4,
|
||||
elevation: 5,
|
||||
},
|
||||
button: {
|
||||
borderRadius: 20,
|
||||
padding: 10,
|
||||
marginVertical: 20,
|
||||
elevation: 2,
|
||||
},
|
||||
buttonOpen: {
|
||||
backgroundColor: '#F194FF',
|
||||
},
|
||||
buttonClose: {
|
||||
backgroundColor: '#2196F3',
|
||||
},
|
||||
textStyle: {
|
||||
color: 'white',
|
||||
fontWeight: 'bold',
|
||||
textAlign: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
export default ({
|
||||
title: "Modal's onShow/onDismiss",
|
||||
name: 'onShow',
|
||||
description:
|
||||
'onShow and onDismiss (iOS only) callbacks are called when modals is shown/dissmissed',
|
||||
render: (): React.Node => <ModalOnShowOnDismiss />,
|
||||
}: RNTesterExampleModuleItem);
|
||||
Reference in New Issue
Block a user