react native经过Animate封装兼容android安卓和ios苹果的Toast提示框

业务须要专门看了react native的Animate动画作出一个Toast提示框react

// Toast
import React from 'react';
import { Animated, Text, View, Easing, Dimensions, Modal,StyleSheet } from 'react-native';
const widthScreen = Dimensions.get('window').width


export default class Toast extends React.Component {
    state = {
        fadeAnim: new Animated.Value(0),  // 透明度初始值设为0
        text: '',  // 显示文本
        refToast: false,  // 是否经过ref绑定
        timer: '',  // 定时器
        callback:null,  // 回调  
    }


    //  执行动画
    shwoToast = (duration = 2000) => {
        Animated.sequence([
            Animated.timing(                  // 随时间变化而执行动画
                this.state.fadeAnim,            // 动画中的变量值
                {
                    easing: Easing.linear,
                    toValue: 1,                   // 透明度最终变为1,即彻底不透明
                    duration: duration,              // 让动画持续一段时间
                }
            ),
        ]).start();                      // 开始执行动画
    }

    show = (text, duration,callback) => {
        this.setTiner(duration)
        this.setState({ text, refToast: true })
        this.state.fadeAnim.setValue(0) // 必需要每次执行都变动一次为0,才能使得动画从0隐藏到1显示
        this.shwoToast()  // 执行动画 
        callback&&callback()  // 回调
    }

    setTiner = () => {
        this.state.timer = setTimeout(() => {
            this.setState({ refToast: false })
            clearTimeout(this.state.timer)
        }, 2000);
    }



    render() {
        let { fadeAnim, refToast } = this.state
        let { showToast, duration } = this.props
        let { width, left } = styles.container
        let text = refToast ? this.state.text : this.props.text

        if (!refToast && showToast) {  //  布尔值判断是否显示Toast
            this.state.fadeAnim.setValue(0) // 必需要每次执行都变动一次为0,才能使得动画从0隐藏到1显示
            this.show(text, duration)  // 执行动画 
            showToast = false  // 执行以后要变为false,不在执行
        }

        //  检查显示文字内容过多宽度变大
        if (text && text.length > 14) {
            width = 200
            left = (widthScreen / 2) - 100
        } else {
            width = 140
            left = (widthScreen / 2) - 70
        }


        const opacity = fadeAnim.interpolate({
            inputRange: [0, 0.5, 1],    //  显示
            outputRange: [0, 5, 0]      //  隐藏
        });

        return (
            <View>
                <Modal
                    animationType="none"
                    transparent={refToast}
                    visible={refToast}
                >
                    <Animated.View                 // 使用专门的可动画化的View组件
                        style={{
                            ...styles.container,
                            opacity: opacity,         // 将透明度指定为动画变量值
                            width,
                            left
                        }}
                    >
                        <View style={styles.bodyView}>
                            <Text style={styles.bodyText}>{text}</Text>
                        </View>
                    </Animated.View>
                </Modal>
            </View>
        );
    }
}


const styles = StyleSheet.create({
    container: {
        position: 'absolute',
        bottom: 80,
        backgroundColor: '#ddd',
        borderRadius: 10,
        height: 'auto',
        padding: 15,
        width: 140,
        left: (widthScreen / 2) - 70,
        zIndex: 9991,
    },
    bodyView: {},
    bodyText: {
        textAlign: 'center'
    }
})

复制代码

一、咱们须要引入toast文件android

// app.js
import ToastView from './src/components/toast/Index';
复制代码

二、在app.js组件中注册redux

// app.js
render() {
    return (
      <Provider store={store}>
        <View style={styles.app}>
          <ToastView ref="toast"  />
          <StackNavigator />
        </View>
      </Provider>
    );
  }
复制代码

三、须要定义一个全局变量,用来全局使用react-native

// app.js
global.Toast = ''   // 全局Toast弹框
复制代码

四、在节点渲染完成以后须要获取refs的绑定bash

app.js
componentDidMount() {
    Toast = this.refs.toast  // 绑定Toast节点
}
复制代码

五、完整代码,我这里包含了redux和路由app

// app.js
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View, BackHandler, ToastAndroid, Dimensions } from 'react-native';
import StackNavigator from './src/router/StackNavigator';
import { Provider } from 'react-redux';
import store from './src/redux/store';
import ToastView from './src/components/toast/Index';
const screenWidth = Dimensions.get('window').width;
import PreventDoublePress from './src/utils/PreventDoublePress'

// 禁止警告
console.disableYellowBox = true;
console.warn('YellowBox is disabled.');
// 打包以后清除全部console警告
if (!__DEV__) {
  global.console = {
    info: () => { },
    log: () => { },
    warn: () => { },
    debug: () => { },
    error: () => { }
  };
}



// 全局
global.loginToken = ''  // 登陆token
global.Toast = ''   // 全局Toast弹框

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      lastBackPressed: 0
    }
  }

  //  页面建立的时候对物理按钮进行监听
  componentWillMount() {
    if (Platform.OS === 'android') {
      BackHandler.addEventListener('hardwareBackPress', this.BackHandler);
    }
  }
  //  页面摧毁的时候销毁监听
  componentWillUnmount() {
    if (Platform.OS === 'android') {
      BackHandler.removeEventListener('hardwareBackPress', this.BackHandler);
    }
  }

  componentDidMount() {
    Toast = this.refs.toast  // 绑定Toast节点
  }

  //  物理返回键 事件触发
  BackHandler = () => {
    if (this.state.lastBackPressed && this.state.lastBackPressed + 2000 >= Date.now()) {
      BackHandler.exitApp()
      return false
    }
    this.state.lastBackPressed = Date.now()
    ToastAndroid.show('再按一次退出应用', ToastAndroid.SHORT)
    return true
  }


  render() {
    return (
      <Provider store={store}>
        <View style={styles.app}>
          <ToastView ref="toast"  />
          <StackNavigator />
        </View>
      </Provider>
    );
  }
}

const styles = StyleSheet.create({
  app: {
    flex: 1,
    flexDirection: 'row'
  },
  toast: {
    position: 'absolute',
    bottom: 50,
    left: screenWidth / 2,
    backgroundColor: '#aaa',
    width: 100,
    height: 'auto',
    zIndex: 999
  },
  toastText: {
    // color:'#000'
  }
});



复制代码

使用方法:在任意一个业务页面中 直接 Toast.show(显示内容)ide

import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { getDate } from '../../../redux/actions'
import { connect } from 'react-redux';
import styles from './Style'


// 首页
class Index extends Component {

  showtoast = () => {
    Toast.show(`Toast显示内容`)
  }


  render() {
    return (
      <View style={styles.container}>
        <Text onPress={() => this.showtoast()}>点击显示Toast框</Text>
      </View>
    );
  }
}



const mapStateToProps = state => ({
  store: state.store
})

export default connect(mapStateToProps)(Index);

复制代码

Toast.show() 里面能够提交有三个参数 参数1:显示的文本 参数2: 显示时长 默认2000毫秒 参数3:回调函数 使用方法:函数

Toast.show('Toast内容',2000,() => {
    // 作些什么
})
复制代码

最终效果flex

Toast

也能够在当前页面单独引用动画

import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { getDate } from '../../../redux/actions'
import { connect } from 'react-redux';
import styles from './Style'
import Toast from '../../../components/toast/Index'


// 首页
class Index extends Component {
  constructor(props) {
    super(props);
    this.state = {
      text:'',
      show:false
    }
  }


  showtoast = () => {
    this.setState({
      text:'Toast显示内容',
      show:true
    })
  }


  render() {
    return (
      <View style={styles.container}>
        <Toast
          text={this.state.text}
          show={this.state.show}
        />
        <Text onPress={() => this.showtoast()}>点击显示Toast框</Text>
      </View>
    );
  }
}



const mapStateToProps = state => ({
  store: state.store
})

export default connect(mapStateToProps)(Index);
复制代码
相关文章
相关标签/搜索