ReactNative реализует Toast

внешний интерфейс GitHub Android React.js

Для инженеров-разработчиков Android Toast знаком, используйте его для отображения подсказки и автоматического ее скрытия. Когда мы разрабатываем приложения RN, мы тоже хотим добиться этого эффекта, это немного сложно, но не сложно, но нам нужно адаптироваться, RN официально предоставляет API ToastAndroid, вы должны угадать имя, когда его увидите, это может только использоваться в Android и не имеет никакого эффекта в iOS. Поэтому нам нужно адаптировать или настроить его. Сегодняшняя статья посвящена настройке Toast, чтобы он мог работать как на Android, так и на iOS и иметь одинаковый эффект работы.

портал исходного кода

определить компоненты

import React, {Component} from 'react';
import {
    StyleSheet,
    View,
    Easing,
    Dimensions,
    Text,
    Animated
} from 'react-native';
import PropTypes from 'prop-types';
import Toast from "./index";

const {width, height} = Dimensions.get("window");
const viewHeight = 35;

class ToastView extends Component {
    static propTypes = {
        message:PropTypes.string,
    };
    dismissHandler = null;

    constructor(props) {
        super(props);
        this.state = {
            message: props.message !== undefined ? props.message : ''
        }
    }

    render() {
        return (
            <View style={styles.container} pointerEvents='none'>
                <Animated.View style={[styles.textContainer]}><Text
                    style={styles.defaultText}>{this.state.message}</Text></Animated.View>
            </View>
        )
    }
    componentDidMount() {
       this.timingDismiss()
    }

    componentWillUnmount() {
        clearTimeout(this.dismissHandler)
    }


    timingDismiss = () => {
        this.dismissHandler = setTimeout(() => {
            this.onDismiss()
        }, 1000)
    };

    onDismiss = () => {
        if (this.props.onDismiss) {
            this.props.onDismiss()
        }
    }
}

const styles = StyleSheet.create({
    textContainer: {
        backgroundColor: 'rgba(0,0,0,.6)',
        borderRadius: 8,
        padding: 10,
        bottom:height/8,
        maxWidth: width / 2,
        alignSelf: "flex-end",
    },
    defaultText: {
        color: "#FFF",
        fontSize: 15,
    },
    container: {
        position: "absolute",
        left: 0,
        right: 0,
        top: 0,
        bottom: 0,
        flexDirection: "row",
        justifyContent: "center",
    }
});
export default ToastView

Сначала импортируйте наши необходимые базовые компоненты и API. Наши пользовательские компоненты должны наследовать их. Размеры используются для получения размера экрана, Easing используется для установки эффекта движения по траектории анимации, а PropTypes используется для определения типа свойства.

Метод рендеринга является для нас точкой входа для определения рендеринга компонента.В крайнем внешнем представлении позиция используется как абсолютная, а левое, правое, верхнее и нижнее значения устанавливаются равными 0, чтобы он заполнил экран, чтобы интерфейсу не разрешено прослушивать события кликов во время отображения Toast. Внутренний вид — это контейнер черного ящика, отображаемый Toast, свойство backgroundColor установлено в форме rgba, цвет — черный, а прозрачность — 0,6. И установите закругленные углы и максимальную ширину на половину ширины экрана. Затем компонент «Текст» используется для отображения конкретной информации подсказки.

Мы также видели, что propTypes используется для определения типа сообщения свойства как строки. Конструктор — это метод построения нашего компонента, есть параметр props, этот параметр — какие-то переданные свойства. Следует отметить, что super(props) должен быть вызван первым в методе построения, иначе будет сообщено об ошибке.Здесь я установил переданное значение в состояние.

Для Toast отображение автоматически исчезнет на некоторое время, мы можем добиться этого эффекта через setTimeout, вызвать этот метод в componentDidMount и установить здесь время на 1000 мс. Затем разрушьте скрытое и разоблачите его. Когда мы используем setTimeout, нам также нужно очистить таймер, когда компонент выгружается. componentWillUnmount вызывается, когда компонент размонтирован. Так что очистите таймер здесь.

# реализуем эффект анимации В приведенном выше примере мы добились эффекта Toast, но отображение и скрытие не слишком анимированы, что немного жестко. Затем мы добавляем несколько анимаций перевода и прозрачности, а затем модифицируем componentDidMount для достижения анимационных эффектов. Добавьте две переменные в компонент

    moveAnim = new Animated.Value(height / 12);
    opacityAnim = new Animated.Value(0);

В предыдущем стиле внутреннего вида нижний набор равен высоте/8. Здесь мы устанавливаем стиль просмотра следующим образом

style={[styles.textContainer, {bottom: this.moveAnim, opacity: this.opacityAnim}]}

Затем измените componentDidMount

 componentDidMount() {
        Animated.timing(
            this.moveAnim,
            {
                toValue: height / 8,
                duration: 80,
                easing: Easing.ease
            },
        ).start(this.timingDismiss);
        Animated.timing(
            this.opacityAnim,
            {
                toValue: 1,
                duration: 100,
                easing: Easing.linear
            },
        ).start();
    }

То есть при отображении дна оно перемещается с высоты/12 на высоту/8, время 80мс, а время выполнения перехода с 0 на 1 100мс. Выше мы видим, что есть свойство easing, передающее кривую скорость выполнения анимации, которую можно реализовать самостоятельно, в Easing API уже много разных эффектов. Вы можете пойти и посмотреть реализацию самостоятельно.Адрес исходного кода https://github.com/facebook/react-native/blob/master/Libraries/Animated/src/Easing.js.Если вы реализуете это самостоятельно, вы можете непосредственно дать функцию расчета.Вы можете посмотреть подражание самостоятельно. #определить время отображения Впереди мы устанавливаем Toast для отображения 1000 мс, мы настраиваем время отображения и ограничиваем количество типов,

        time: PropTypes.number

Время обработки в конструкторе

            time: props.time && props.time < 1500 ? Toast.SHORT : Toast.LONG,

Здесь я имел дело с отображением времени в виде двух значений SHORT и LONG, конечно, вы можете сами справиться с желаемым эффектом. Затем вам нужно только изменить время 1000 в TimingDismiss и записать его как this.state.time. #обновление компонента Когда свойство обновляется снова, когда компонент уже существует, нам нужно обработать это, обновить сообщение и время в состоянии, очистить таймер и переназначить его.


    componentWillReceiveProps(nextProps) {
     this.setState({
            message: nextProps.message !== undefined ? nextProps.message : '',
            time: nextProps.time && nextProps.time < 1500 ? Toast.SHORT : Toast.LONG,
        })
        clearTimeout(this.dismissHandler)
        this.timingDismiss()
    }

Регистрация компонента

Чтобы наши определенные компоненты вызывались в виде API, а не записывались в методе рендеринга, поэтому мы определяем последующий компонент.

import React, {Component} from "react";
import {StyleSheet, AppRegistry, View, Text} from 'react-native';

viewRoot = null;

class RootView extends Component {
    constructor(props) {
        super(props);
        console.log("constructor:setToast")
        viewRoot = this;
        this.state = {
            view: null,
        }
    }

    render() {
        console.log("RootView");
        return (<View style={styles.rootView} pointerEvents="box-none">
            {this.state.view}
        </View>)
    }

    static setView = (view) => {
//此处不能使用this.setState
        viewRoot.setState({view: view})
    };
}


const originRegister = AppRegistry.registerComponent;

AppRegistry.registerComponent = (appKey, component) => {

    return originRegister(appKey, function () {
        const OriginAppComponent = component();

        return class extends Component {

            render() {
                return (
                    <View style={styles.container}>
                        <OriginAppComponent/>
                        <RootView/>
                    </View>
                );
            };
        };
    });
};
const styles = StyleSheet.create({
    container: {
        flex: 1,
        position: 'relative',
    },
    rootView: {
        position: "absolute",
        left: 0,
        right: 0,
        top: 0,
        bottom: 0,
        flexDirection: "row",
        justifyContent: "center",
    }
});
export default RootView

RootView — это определенный нами корневой компонент, реализованный, как описано выше, зарегистрированный через AppRegistry.registerComponent. #wrapped для внешних вызовов

import React, {
    Component,
} from 'react';
import RootView from '../RootView'
import ToastView from './ToastView'


class Toast {
    static LONG = 2000;
    static SHORT = 1000;

    static show(msg) {
        RootView.setView(<ToastView
            message={msg}
            onDismiss={() => {
                RootView.setView()
            }}/>)
    }

    static show(msg, time) {
        RootView.setView(<ToastView
            message={msg}
            time={time}
            onDismiss={() => {
                RootView.setView()
            }}/>)
    }
}

export default Toast

В Toast определены две статические переменные, указывающие, что отображаемое время предназначено для внешнего использования. Затем предоставьте два статических метода, в которых вызывается метод setView для RootView, чтобы установить для ToastView корневое представление.

#использовать Сначала импортируйте вышеупомянутый Toast, а затем вызовите следующий метод

                    Toast.show("测试,我是Toast");
                    //能设置显示时间的Toast
                    Toast.show("测试",Toast.LONG);

Что ж, введение статьи закончено. Если вы хотите увидеть полный код, вы можете ввести меняGitHubПроверить. Если в тексте есть неточности или ошибки, просьба указать. С Новым годом наконец.