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(); // 手动关闭
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容