# React Native 封裝Toast ## 前言 > 使用react native的小伙伴都知道,官方並未提供輕提示組件,只提供了ToastAndroid API,顧名思義,只能再安卓環境下使用,對於ios就愛莫能助,故此,只能通過官方的核心組件,自行封裝,實現Toast功能 ## 實現 * ...
React Native 封裝Toast
前言
使用react native的小伙伴都知道,官方並未提供輕提示組件,只提供了ToastAndroid API,顧名思義,只能再安卓環境下使用,對於ios就愛莫能助,故此,只能通過官方的核心組件,自行封裝,實現Toast功能
實現
創建文件
首先我們需要創建一個Toast組件,引入對應需要的依賴,icon等等
聲明數據類型,通用方法
import React, {Component} from 'react';
import {View, Text, StyleSheet, Animated, Easing} from 'react-native';
import icon_success from '../assets/images/icon-success.png';
import icon_error from '../assets/images/icon-error.png';
import icon_loading from '../assets/images/icon-loading.png';
import icon_warning from '../assets/images/icon-warning.png';
type StateType = {
isVisible: boolean;
icon: any;
message: string;
};
type ParamsType = string | {message: string; duration?: number};
function getParams(data: ParamsType): {message: string; duration: number} {
let msg!: string;
let dur!: number;
if (typeof data === 'string') {
msg = data;
dur = 2000;
} else {
msg = data.message;
dur = data.duration != null ? data.duration : 2000;
}
return {
message: msg,
duration: dur,
};
}
實現樣式和UI層次渲染
我們需要創建一個class,接收參數,並根據不同的條件渲染:success、error、warning、show、loading等
並拋出自己的實例
class ToastComponent extends Component<{} | Readonly<{}>, StateType> {
timeout!: NodeJS.Timeout;
rotate: Animated.Value = new Animated.Value(0);
constructor(props: {} | Readonly<{}>) {
super(props);
this.state = {
isVisible: false,
icon: null,
message: '',
};
Toast.setToastInstance(this);
}
showToast(icon: any, message: string, duration: number) {
this.setState({
isVisible: true,
icon,
message,
});
if (duration !== 0) {
const timeout = setTimeout(() => {
this.closeToast();
}, duration);
this.timeout = timeout;
}
}
showRotate() {
Animated.loop(
Animated.timing(this.rotate, {
toValue: 360,
duration: 1000,
easing: Easing.linear,
useNativeDriver: true,
}),
).start();
}
closeToast() {
this.setState({
isVisible: false,
icon: null,
message: '',
});
if (this.timeout) {
clearTimeout(this.timeout);
}
}
render() {
const {isVisible, icon, message} = this.state;
return isVisible ? (
<View style={style.root}>
<View style={[style.main, icon === null ? null : style.mainShowStyle]}>
{icon && (
<Animated.Image
style={[
style.icon,
{
transform: [
{
rotate: this.rotate.interpolate({
inputRange: [0, 360],
outputRange: ['0deg', '360deg'],
}),
},
],
},
]}
source={icon}
/>
)}
<Text style={style.tip}>{message}</Text>
</View>
</View>
) : null;
}
}
const style = StyleSheet.create({
root: {
height: '100%',
backgroundColor: 'transparent',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 99999,
alignItems: 'center',
justifyContent: 'center',
},
main: {
maxWidth: 200,
maxHeight: 200,
backgroundColor: '#00000099',
borderRadius: 8,
alignItems: 'center',
justifyContent: 'center',
padding: 20,
},
mainShowStyle: {
minWidth: 140,
minHeight: 140,
},
icon: {
width: 36,
height: 36,
resizeMode: 'cover',
marginBottom: 20,
},
tip: {
fontSize: 14,
color: '#fff',
fontWeight: 'bold',
textAlign: 'center',
},
});
拋出對外調用的方法
此時我們需要再聲明一個class,對外拋出方法以供調用
最後導出即可
class Toast extends Component<{} | Readonly<{}>, {} | Readonly<{}>> {
static toastInstance: ToastComponent;
static show(data: ParamsType) {
const {message, duration} = getParams(data);
this.toastInstance.showToast(null, message, duration);
}
static loading(data: ParamsType) {
const {message, duration} = getParams(data);
this.toastInstance.showToast(icon_loading, message, duration);
this.toastInstance.showRotate();
}
static success(data: ParamsType) {
const {message, duration} = getParams(data);
this.toastInstance.showToast(icon_success, message, duration);
}
static error(data: ParamsType) {
const {message, duration} = getParams(data);
this.toastInstance.showToast(icon_error, message, duration);
}
static warning(data: ParamsType) {
const {message, duration} = getParams(data);
this.toastInstance.showToast(icon_warning, message, duration);
}
static clear() {
if (this.toastInstance) {
this.toastInstance.closeToast();
}
}
static setToastInstance(toastInstance: ToastComponent) {
this.toastInstance = toastInstance;
}
render() {
return null;
}
};
export {Toast, ToastComponent};
組件掛載
我們需要將UI層組件在入口TSX文件進行掛載,不然Toast無法渲染
/* APP.tsx */
import React from 'react';
import {StatusBar} from 'react-native';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {ToastComponent} from './src/components/Toast';
const Stack = createStackNavigator();
function App(): JSX.Element {
return (
<SafeAreaProvider>
<StatusBar barStyle="dark-content" backgroundColor="#EAF7FF" />
<ToastComponent />
</SafeAreaProvider>
);
}
export default App;
API調用
掛載完成,接下來,在我們需要用到的地方,調用即可
import {Toast} from '../../components/Toast';
//
Toast.success('登錄成功');
Toast.error('密碼錯誤');
Toast.warning('我是警告');
Toast.loading('載入中,請稍後');
Toast.loading({message: "我是不關閉的Toast", duration: 0})
Toast.success({message: "我是2秒後關閉的Toast", duration: 2000});
Toast.clear(); // 手動關閉