欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

react-native自定义Modal模态框|仿ios、微信弹窗RN版

程序员文章站 2023-02-24 12:57:17
前序 纵观每个优质项目,无论web端还是native原生应用开发,弹窗都是不可忽视的一环,能很大程度上直接决定用户体验。如:微信、支付宝、ios都有很成熟的一套弹窗UI展示场景。 最近一直沉迷在react-native开发研究中,学习起来发现没有想象的难,不过也采坑了不少。鉴于之前有基于h5和小程序 ......

前序

纵观每个优质项目,无论web端还是native原生应用开发,弹窗都是不可忽视的一环,能很大程度上直接决定用户体验。如:微信、支付宝、ios都有很成熟的一套弹窗ui展示场景。

最近一直沉迷在react-native开发研究中,学习起来发现没有想象的难,不过也采坑了不少。鉴于之前有基于h5和小程序技术开发过自定义弹窗的经验,就想着用react-native技术实现msg信息框|alert提示框|confirm确认框|toast弱提示/loading|仿ios、android弹窗,就有了这个rnpop弹窗组件rn版。

效果图

仿真模拟器上画质有些次,真机实测完美,可忽略这一点

react-native自定义Modal模态框|仿ios、微信弹窗RN版

看了上图,是不是觉得调用方式还挺多的,没错,很丰富的应用场景

◆ rnpop弹窗组件目录结构

react-native自定义Modal模态框|仿ios、微信弹窗RN版

◆ 引入方式及调用

import rnpop from '../utils/rnpop/rnpop.js'

react-native自定义Modal模态框|仿ios、微信弹窗RN版

显示:this.refs.rnpop.show({...options});
隐藏:this.refs.rnpop.hide();
/**
 * --------- react-native弹窗演示(普通型弹窗) ---------
 */
//msg提示
handlepress01 = ()=> {
    let rnpop = this.refs.rnpop
    rnpop.show({
        anim: 'fadein',
        content: 'msg消息提示框(5s后窗口关闭)',
        shade: true,
        shadeclose: false,
        time: 5,
        xtime: true,
    });
}

//msg提示(黑色背景)
handlepress02 = ()=> {
    let rnpop = this.refs.rnpop
    rnpop.show({
        content: '自定义弹窗背景',
        shade: false,
        style: {backgroundcolor: 'rgba(17,17,17,.7)', borderradius: 6},
        contentstyle: {color: '#fff', padding: 10},
        time: 2
    });
}

toast弱提示可自定义loading | success | info | error四种图标

//toast演示
handlepress15 = ()=> {
    let rnpop = this.refs.rnpop
    rnpop.show({
        skin: 'toast',
        content: '操作成功',
        icon: 'success', //success | info | error | loading
        shade: false,
        time: 3
    });
}
//ios居中对话框
handlepress17 = ()=> {
    let rnpop = this.refs.rnpop
    rnpop.show({
        skin: 'footer',
        position: 'center',
        content: '如果您喜欢探鱼,请给我们个好评,也可以直接反馈意见给我们!',
        shadeclose: true,
        
        btns: [
            {
                text: '给个好评',
                style: {color: '#30a4fc'},
                onpress() {
                    console.log('您点击了给个好评!');
                    
                    //回调函数
                    rnpop.show({
                        anim: 'fadein',
                        content: '感谢您的好评,我们会再接再厉!',
                        shade: true,
                        time: 3
                    });
                }
            },
            {
                text: '不好用,我要提意见',
                style: {color: '#30a4fc'},
                onpress() {
                    // ...
                }
            },
            {
                text: '残忍的拒绝',
                style: {color: '#30a4fc'},
                onpress() {
                    rnpop.close();
                }
            }
        ]
    });
}

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

react-native自定义Modal模态框|仿ios、微信弹窗RN版

/**
 * @title         react-native弹窗插件 rnpop-v1.0 beta (utf-8)
 * @author        andy
 * @create        2019/07/30 10:00:50 gmt+0800 (中国标准时间)
 * @aboutme    q:282310962  wx:xy190310
 */

'use strict'

import react, {component} from 'react'
import {
    stylesheet, dimensions, pixelratio, touchablehighlight, modal, view, text, image, activityindicator, alert
} from 'react-native'

const pixel = pixelratio.get()
const {width, height} = dimensions.get('window')

export default class rnpop extends component{
    /**************************
     *    弹窗配置参数
     */
    static defaultprops = {
        isvisible: false,       //弹窗显示

        id: 'rnpop',            //弹窗id标识
        title: '',              //标题
        content: '',            //内容
        style: null,            //自定义弹窗样式 {object}
        contentstyle: null,     //内容样式
        skin: '',               //自定义弹窗风格
        icon: '',               //自定义弹窗图标

        shade: true,            //遮罩层
        shadeclose: true,       //点击遮罩层关闭
        opacity: '',            //遮罩层透明度
        xclose: false,          //自定义关闭按钮
        time: 0,                //弹窗自动关闭秒数
        xtime: false,           //显示关闭秒数

        anim: 'scalein',        //弹窗动画
        follow: null,            //跟随定位(适用于在长按位置定位弹窗)
        position: '',           //弹窗位置
        zindex: 9999,           //层叠等级

        btns: null,             //弹窗按钮(不设置则不显示按钮)[{...options}, {...options}]
    }

    constructor(props){
        super(props)
        this.state = { ...this.props }
        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'),
        }

        ...
        
    }

    /**************************
     *    显示弹窗事件(处理传参)
     */
    show = (args) => {
        this.setstate({
            ...this.props, ...args, isvisible: true
        })
    }

    /**************************
     *    关闭弹窗事件
     */
    close = () => {
        console.log('关闭')
        this.setstate({
            ...this.props
        })
        this.timer && cleartimeout(this.timer)
        delete this.timer
    }
}

◆ react-native自定义弹窗模板

<modal transparent={true} visible={opt.isvisible} onrequestclose={this.close}>
    <view style={styles.rnpop__ui_panel}>
        {/* 遮罩 */}
        { opt.shade && <view style={styles.rnpop__ui_mask} ontouchend={opt.shadeclose ? this.close : null} /> }
        {/* 窗体 */}
        <view style={styles.rnpop__ui_main}>
            <view style={styles.rnpop__ui_child}>
                {/* 标题 */}
                { opt.title ? <view style={[styles.rnpop__ui_tit]}><text style={[styles.rnpop__ui_titxt]}>{opt.title}</text></view> : null }
                {/* 内容 */}
                { opt.content ? <view style={[styles.rnpop__ui_cnt]}>
                    ...
                    <text style={[styles.rnpop__ui_cntxt, opt.contentstyle]}>{opt.content}</text>
                </view> : null }
                {/* 按钮 */}
                <view style={[styles.rnpop__ui_btnwrap]}>
                ...
                </view>
            </view>
        </view>
    </view>
</modal>

◆ 附上之前的h5和小程序弹窗

h5手机端弹窗:

h5网页版弹窗:

小程序弹窗: