模態框應用於界面彈窗,爲用戶提供通知、選擇、瀏覽等功能的組件。在RN中,模態框通過Moadl標籤引用。使用時注意,可以把Modal看成一個僅提供功能的外殼,它不包含任何樣式,只負責顯示/隱藏和動畫效果實現。Modal的子組件通常爲一個View容器,在該View容器實現渲染界面和樣式相關。在很多APP應用模態框的時候,出於視覺的優化,Modal子組件最外層的View容器爲一層佔滿全屏的半透明背景層。
Modal的屬性:
屬性 | 描述 |
---|---|
animationType |
指定了 modal 的動畫類型。類型:slide 從底部滑入滑出|fade 淡入淡出|none 沒有動畫 |
transparent |
背景是否透明,默認爲白色,當爲true時表示背景爲透明 |
visible |
boolean值,是否顯示 modal 窗口 |
onRequestClose |
回調會在用戶按下 Android 設備上的後退按鍵或是 Apple TV 上的菜單鍵時觸發。請務必注意本屬性在 Android 平臺上爲必填,且會在 modal 處於開啓狀態時阻止BackHandler事件 |
onShow |
回調函數會在 modal 顯示時調用 |
貼士代碼:
import React from 'react';
import { View, Text, Modal, StyleSheet, Button } from 'react-native';
class ModalComp extends React.Component{
state = {
modalVisible: false
};
_openModalWin = () => {
this.setState({modalVisible: true});
}
_closeModalWin = () => {
this.setState({modalVisible: false});
}
render(){
return(
<View style={styles.container}>
<View style={styles.contentStyle}>
<Text style={styles.contentTextStyle}>
ModalComp
</Text>
<Button
title="打開Modal窗口"
color="#841584"
onPress={this._openModalWin}
/>
</View>
<Modal
animationType='fade' // 指定了 modal 的動畫類型。類型:slide 從底部滑入滑出|fade 淡入淡出|none 沒有動畫
transparent={true} // 背景是否透明,默認爲白色,當爲true時表示背景爲透明。
visible={this.state.modalVisible} // 是否顯示 modal 窗口
onRequestClose={() => { this._closeModalWin(); }} // 回調會在用戶按下 Android 設備上的後退按鍵或是 Apple TV 上的菜單鍵時觸發。請務必注意本屬性在 Android 平臺上爲必填,且會在 modal 處於開啓狀態時阻止BackHandler事件
onShow={()=>{console.log('modal窗口顯示了');}} // 回調函數會在 modal 顯示時調用
>
<View style={styles.modalLayer}>
<View style={styles.modalContainer}>
<Text style={styles.modalTitleStyle}>這是個Modal窗口!</Text>
<View style={styles.modalButtonStyle}>
<Button
title='取消'
color="#A4A4A4"
onPress={this._closeModalWin}
></Button>
</View>
</View>
</View>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
contentStyle: {
padding:30
},
contentTextStyle: {
textAlign: 'center',
fontSize: 26
},
modalLayer: {
backgroundColor: 'rgba(0, 0, 0, 0.45)',
flex: 1,
justifyContent: 'center',
padding: 32
},
modalContainer: {
height: 300,
backgroundColor: 'white',
justifyContent: 'center'
},
modalTitleStyle: {
textAlign: 'center',
fontSize: 26
},
modalButtonStyle: {
paddingLeft: 30,
paddingRight: 30,
marginTop: 10
}
});
export default ModalComp;
效果:
還有一種常見的模態框應用場景,就是從底部彈出一組可選菜單,這類組件叫做ActionSheet組件。
貼上代碼:ActionSheet組件
import React, {Component} from 'react';
import {
View,
StyleSheet,
Text,
Modal,
TouchableOpacity,
Dimensions
} from 'react-native';
import PropTypes from 'prop-types';
const {width} = Dimensions.get('window');
class ActionSheetComp extends Component{
// 入參類型
static propTypes={
items:PropTypes.array,
modalTitle:PropTypes.string,
visible: PropTypes.bool
}
// 默認值
static defaultProps={
items:[
{
title: '拍照',
click: () => {
console.log('拍照');
}
},
{
title: '錄像',
click: () => {
console.log('錄像');
}
}
],
modalTitle:'你需要拍照或錄像?',
visible: false
}
state = {
modalVisible: this.props.visible,
};
// 該鉤子函數表示當父組件的props入參改變時調用,常用於父組件入參變化影響子組件渲染
UNSAFE_componentWillReceiveProps(newProps){
this.setState({modalVisible:newProps.visible});
}
cancelModal(){
this.setState({modalVisible:false});
}
render(){
let actionSheets = this.props.items.map((item,i)=>{
return(
<TouchableOpacity
key={i}
style={styles.actionItem}
onPress={item.click}>
<Text style={styles.actionItemTitle}>
{item.title}
</Text>
</TouchableOpacity>
);
});
return (
<Modal
animationType="slide"
visible={this.state.modalVisible}
transparent={true}
onRequestClose={()=>this.setState({modalVisible:false})}
>
<View style={styles.modalStyle}>
<View style={styles.subView}>
<View style={styles.itemContainer}>
<Text style={styles.actionTitle}>
{this.props.modalTitle}
</Text>
{actionSheets}
</View>
<View style={[styles.itemContainer]}>
<TouchableOpacity
style={[styles.actionItem, {borderTopWidth:0}]}
onPress={()=>this.setState({modalVisible:false})}>
<Text style={styles.actionItemTitle}>取消</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
);
}
}
const styles = StyleSheet.create({
modalStyle:{
justifyContent:'flex-end',
alignItems:'center',
flex:1
},
subView:{
justifyContent:'flex-end',
alignItems:'center',
alignSelf:'stretch',
width:width,
},
itemContainer:{
marginLeft:15,
marginRight:15,
marginBottom:15,
borderRadius:6,
backgroundColor:'#fff',
justifyContent:'center',
alignItems:'center',
},
actionItem:{
width:width-30,
height:45,
alignItems:'center',
justifyContent:'center',
borderTopColor:'#cccccc',
borderTopWidth:0.5,
},
actionTitle:{
fontSize:13,
color:'#808080',
textAlign:'center',
paddingTop:10,
paddingBottom:10,
paddingLeft:15,
paddingRight:15,
},
actionItemTitle:{
fontSize:16,
color:'#444444',
textAlign:'center',
},
});
export default ActionSheetComp;
引用組件:
import React, { Component } from 'react';
import { View, Button } from 'react-native';
import ActionSheetComp from '../example/comp/ActionSheetComp';
class MainView extends Component {
state = {
visible: false
}
_showModal = () => {
this.setState({visible:true});
}
render(){
return (
<View style={{flex:1, backgroundColor: '#E4E4E4'}}>
<Button
title='顯示'
onPress={this._showModal}
/>
<ActionSheetComp visible={this.state.visible} />
</View>
);
}
}
export default MainView;
效果: