react-native 仿原生自定義彈窗|iOS/Android 彈窗效果

xiaoyan2015發表於2019-08-07

react-native仿原生自定義彈窗|ios/android彈窗效果
react-native仿原生自定義彈窗|ios/android彈窗效果

基於react-native技術開發的自定義模態框rnPop,結合原生Modal功能,實現類似android、ios、微信彈窗效果。

目錄結構
react-native仿原生自定義彈窗|ios/android彈窗效果

呼叫方法一:

// 引入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仿原生自定義彈窗|ios/android彈窗效果

react-native仿原生自定義彈窗|ios/android彈窗效果

react-native仿原生自定義彈窗|ios/android彈窗效果

react-native仿原生自定義彈窗|ios/android彈窗效果

react-native仿原生自定義彈窗|ios/android彈窗效果

另外,react-native自定義toast支援四種圖示 success/info/error/loading

//Toast演示
handlePress15 = ()=> {
    rnPop({
        skin: 'toast',
        content: '操作成功',
        icon: 'success', //success | info | error | loading
        shade: false,
        time: 3
    });
}

react-native仿原生自定義彈窗|ios/android彈窗效果

react-native仿原生自定義彈窗|ios/android彈窗效果

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('您點選了更新!');
                }
            }
        ]
    });
}

react-native仿原生自定義彈窗|ios/android彈窗效果

react-native仿原生自定義彈窗|ios/android彈窗效果

react-native仿原生自定義彈窗|ios/android彈窗效果

react-native仿原生自定義彈窗|ios/android彈窗效果

react-native仿原生自定義彈窗|ios/android彈窗效果

react-native仿原生自定義彈窗|ios/android彈窗效果

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>
    )
}

react-native仿原生自定義彈窗|ios/android彈窗效果

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

react-native仿原生自定義彈窗|ios/android彈窗效果

本文為原創文章,未經作者允許不得轉載,歡迎大家一起交流 QQ(282310962) wx(xy190310)

相關文章