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);
複製代碼
相關文章
相關標籤/搜索