基於react-native技術開發的自定義模態框rnPop,結合原生Modal功能,實現類似android、ios、微信彈窗效果。
目錄結構
呼叫方法一:
// 引入rnPop.js元件
import RNPop from '../utils/rnPop/rnPop.js'
render() {
return (
<View style={styles.container}>
...
{/* 引入彈窗模板 */}
<RNPop ref="rnPop" />
</View>
)
}
顯示:this.refs.rnPop.show({...options});
隱藏:this.refs.rnPop.hide();
呼叫方法二:
利用react-native全域性變數global,對外暴露介面
/**************************
* 例項化彈窗介面
*/
const Popup = (args) => {
RNPop.show(args)
}
Popup.close = () => {
RNPop.close()
}
global.rnPop = Popup
可以非常優雅的使用rnPop({…options}) 、 rnPop.close()方式進行彈窗呼叫
//msg提示
handlePress01 = ()=> {
rnPop({
content: 'msg訊息提示框(5s後視窗關閉)',
shade: true,
shadeClose: false,
time: 5,
xtime: true,
anim: 'fadeIn',
});
}
//msg提示(黑色背景)
handlePress02 = ()=> {
rnPop({
content: '自定義彈窗背景',
shade: false,
style: {backgroundColor: 'rgba(17,17,17,.7)', borderRadius: 6},
contentStyle: {color: '#fff', padding: 10},
time: 2
});
}
另外,react-native自定義toast支援四種圖示 success/info/error/loading
//Toast演示
handlePress15 = ()=> {
rnPop({
skin: 'toast',
content: '操作成功',
icon: 'success', //success | info | error | loading
shade: false,
time: 3
});
}
ios彈窗效果及android效果
//ios對話方塊
handlePress16 = ()=> {
rnPop({
skin: 'footer',
content: 'Apple ID \n 282310962@qq.com',
shadeClose: false,
anim: 'bottom',
btns: [
{
text: '登出賬號',
style: {color: '#30a4fc'},
onPress() {
console.log('您點選了恢復!');
}
},
{
text: '刪除',
style: {color: '#e63d23'},
onPress() {
console.log('您點選了刪除!');
//刪除回撥提示
rnPop({
anim: 'fadeIn',
content: '您點選了刪除功能',
shade: true,
time: 3
});
}
},
{
text: '取消',
style: {color: '#999'},
onPress() {
console.log('您點選了取消!');
rnPop.close();
}
}
]
});
}
// android 樣式
handlePress20 = ()=>{
rnPop({
skin: 'android',
title: '發現新版本',
content: '程式設計師GG緊急修復了一個閃退bug,給您帶來的不便敬請諒解。\n\n[近期更新]\n 1、新增資訊&話題入口 \n 2、新增詳情頁面長按分享功能',
shadeClose: false,
btns: [
{
text: '知道了',
onPress() {
rnPop.close();
console.log("知道了");
}
},
{
text: '更新',
style: {color: '#4eca33'},
onPress() {
console.log('您點選了更新!');
}
}
]
});
}
emmm,看到這裡是不是感覺還不錯,不過總感覺少了點啥。
沒錯,上面彈窗都是傳入的string字串, 能不能傳入Text、View自定義模板呢,答案是可以的。
還支援對傳入content引數進行自定義模板 content: string | object
// 自定義呼叫
handlePressAA = () => {
rnPop({
content: (
<DefineCp />
// <View style={{alignItems: 'center', justifyContent: 'center'}}>
// <Image style={{height: 200, width: 200}} source={require('../assets/qrcode.jpg')} />
// <Text style={{color: '#999'}}>長按或掃一掃二維碼,加我好友</Text>
// <View><Text onPress={rnPop.close} style={{backgroundColor: '#61dafb', borderRadius: 20, color: '#fff', marginTop: 15, marginBottom: 10, paddingVertical: 5, paddingHorizontal: 50}}>儲存二維碼</Text></View>
// </View>
),
anim: 'bottom'
});
}
// 自定義模板
const DefineCp = () => {
return (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Image style={{height: 200, width: 200}} source={require('../assets/qrcode.jpg')} />
<Text style={{color: '#999'}}>長按或掃一掃二維碼,加我好友</Text>
<View><Text onPress={rnPop.close} style={{backgroundColor: '#61dafb', borderRadius: 20, color: '#fff', marginTop: 15, marginBottom: 10, paddingVertical: 5, paddingHorizontal: 50}}>儲存二維碼</Text></View>
</View>
)
}
/**
* @Title react-native彈窗外掛 rnPop-v1.0 beta (UTF-8)
* @Create 2019/08/01 10:00:50 GMT+0800 (中國標準時間)
* @Author andy Q:282310962 wx:xy190310
*/
'use strict'
import React, {Component} from 'react'
import {
Animated, Easing, StyleSheet, Dimensions, PixelRatio, TouchableHighlight, Modal, View, Text, Image, ActivityIndicator
} from 'react-native'
const pixel = PixelRatio.get()
const {width, height} = Dimensions.get('window')
export default class RNPop extends Component{
/**************************
* 彈窗配置引數
*/
static defaultProps = {
isVisible: false, //彈窗顯示
title: '', //標題
content: '', //內容
style: null, //自定義彈窗樣式 {object}
contentStyle: null, //內容樣式
skin: '', //自定義彈窗風格
icon: '', //自定義彈窗圖示
shade: true, //遮罩層
shadeClose: true, //點選遮罩層關閉
opacity: '', //遮罩層透明度
time: 0, //彈窗自動關閉秒數
xtime: false, //顯示關閉秒數
anim: 'scaleIn', //彈窗動畫(scaleIn / fadeIn / top / bottom / left / right)
follow: null, //跟隨定位(適用於在長按位置定位彈窗)
position: '', //彈窗位置
btns: null, //彈窗按鈕(不設定則不顯示按鈕)[{...options}, {...options}]
}
constructor(props){
super(props)
this.state = {
...this.props,
animatedValue: new Animated.Value(0),
}
this.timer = null
}
render(){
let opt = this.state
// __自定義toast圖示
let slotImg = {
success: require('./skin/success.png'),
error: require('./skin/error.png'),
info: require('./skin/info.png'),
}
return (
...
)
}
// 執行動畫
in = () => {
Animated.timing(
this.state.animatedValue, {easing: Easing.linear, duration: 300, toValue: 1}
).start()
}
out = () => {
Animated.timing(
this.state.animatedValue, {easing: Easing.linear, duration: 100, toValue: 0}
).start(()=>{
this.setState({
...this.props
})
})
this.timer && clearTimeout(this.timer)
delete this.timer
}
/**************************
* 顯示彈窗事件(處理傳參)
*/
static show = (args) => {
_this.setState({
..._this.props, ...args, isVisible: true
}, _this.in)
}
/**************************
* 關閉彈窗事件
*/
static close = () => {
_this.out()
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結