mh-rn-component
Version:
122 lines (120 loc) • 3.3 kB
Flow
import React, { useEffect, useState } from 'react'
import { Animated, View, Text, StyleSheet, TouchableWithoutFeedback, Easing, StyleProp, ViewStyle, ScrollView } from 'react-native';
import Overlay from '../Overlay'
// import { useHeaderHeight } from '@react-navigation/elements'
import Icon from '../Icon'
import { ToastType } from "./types"
export interface Props extends ToastType {
show?: boolean
onChange?: (value: any) => void
}
const Toast = ({
message = "成功",
show = false,
icon,
iconSize = 48,
overlayNeed = true, //* 是否需要遮罩层 默认true
overlay = false,
closeOnClickOverlay = true,
duration = 2000,
color = "#fff",
position = "middle",
loading = false,
...rest
}: Props) => {
const onChange = (value?: boolean) => {
rest?.onChange && (rest.id ? rest?.onChange(rest.id) : rest?.onChange(false))
}
// 隐藏 2000s后隐藏
const hide = () => {
if (duration === 0) {
return
}
const tt = setTimeout(() => {
onChange()
clearTimeout(tt)
}, Number(duration))
}
const turn = new Animated.Value(0)
useEffect(() => {
hide()
}, [show])
useEffect(() => {
Animated.loop(
Animated.timing(turn, {
toValue: 1,
duration: 1000,
easing: Easing.linear,
useNativeDriver: false,
}),
{
iterations: -1
}
).start();
// turn.setValue(360)
}, [loading])
const lodingDom = () => {
return (
<TouchableWithoutFeedback>
<Animated.View style={{
transform: [{
rotateZ: turn.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
}),
},]
}}>
<Icon color={color} name={icon} size={Number(iconSize)}></Icon>
</Animated.View>
</TouchableWithoutFeedback>
)
}
return (
<>
{overlayNeed ?
<Overlay show={show} onChange={() => closeOnClickOverlay && onChange(false)} style={[!overlay && { backgroundColor: '', }]}>
<View style={StyleSheet.flatten([styles.toast, position !== "middle" && styles[`position_${position}`]])}>
{loading && lodingDom()}
{(!loading && icon) && <Icon color={color} name={icon} size={Number(iconSize)}></Icon>}
<Text style={{ color: color }}>{message}</Text>
</View>
</Overlay>
:
<View pointerEvents="none" style={[styles.no_overlay_toast, { display: show ? 'flex' : 'none' }]}>
<View style={[styles.toast]}>
{loading && lodingDom()}
{(!loading && icon) && <Icon color={color} name={icon} size={Number(iconSize)}></Icon>}
<Text style={{ color: color }}>{message}</Text>
</View>
</View>}
</>
)
}
const styles = StyleSheet.create({
toast: {
borderRadius: 6,
padding: 16,
overflow: "hidden",
backgroundColor: 'rgba(0, 0, 0, .4)',
minWidth: 96,
alignItems: "center",
position: "absolute",
},
no_overlay_toast: {
width: '100%',
height: '100%',
flex: 1,
alignItems: "center",
justifyContent: "center",
position: "absolute",
top: 0,
left: 0,
},
position_top: {
top: "10%",
},
position_bottom: {
bottom: "10%",
}
})
export default Toast