一、简介
之前和大家分享的自定义View内容,我们知道自定义View一般分为三个步骤:
(1)定义属性、状态
(2)定义组件行为
(3)绘制布局
(4)定义样式
二、分析
App中的提示(Toast)想必大家都不陌生,RN中也提供了ToastAndroid,但是由于仅能在Android平台使用,所以出现了很多开源的三方依赖库,例如react-native-root-toast等等。那么这种该如何实现呢?
1、Toast提示框大致由三部分组成:
(2)显示时长
(3)显示位置
(4)背景
我们可以根据这些来定义基本属性。
2、Toast的的状态分为两种:
(1)显示
(2)隐藏
显示/隐藏的行为我们可以通过state状态来控制。
分析了以上思路,那么就是撸码的节奏了。
三、实现
(1)定义属性、状态:
(2)定义组件行为
- // 定义props
- static propTypes = {
- textStyle: ViewPropTypes.style,contentStyle: ViewPropTypes.style,containerStyle: ViewPropTypes.style,position: PropTypes.oneOf([
- 'top','center','bottom'
- ])
- }
- //初始化 默认 props
- static defaultProps = {
- position: 'center'
- }
- constructor(props) {
- super(props);
- this.state = {
- text: '',isShow: false,opacityAnimate: new Animated.Value(OPACITY) // 动画 值初始化
- };
- // 当前显示状态
- this.isShow = false;
- // 初始化默认显示时长为SHORT
- this.duration = DURATION.SHORT;
- }
(3)绘制布局
- /**
- * 显示
- */
- show(text,duration) {
- if(duration >= DURATION.LONG) {
- this.duration = DURATION.LONG;
- } else {
- this.duration = DURATION.SHORT;
- }
- // 显示
- this.setState({
- text: text,isShow: true
- });
- this.isShow = true;
- this.state.opacityAnimate.setValue(OPACITY);
- // 执行隐藏操作
- this.hide();
- }
- /**
- * 隐藏
- */
- hide() {
- // 隐藏状态下不执行操作
- if(!this.isShow) {
- return;
- }
- this.animateTimer && clearTimeout(this.animateTimer);
- this.animateTimer = setTimeout(()=>{
- // 开启动画
- Animated.timing(
- this.state.opacityAnimate,{
- toValue: 0.0,duration: 600
- }
- ).start(()=>{
- // 动画结束后,初始化状态
- this.setState({
- isShow: false
- })
- this.isShow = false;
- })
- },this.duration);
- }
(4)定义样式(建议单独封装样式,在组件中引用,遵循模块化开发)
- render() {
- let top;
- switch(this.props.position){
- case 'top':
- top = 30;
- break;
- case 'center':
- top = height / 2;
- break;
- case 'bottom':
- top = height - 100;
- break;
- default:
- break;
- }
- return this.state.isShow ?
- <View
- pointerEvents={ 'none' }
- style={[ styles.container,{ top: top } ]}>
- <Animated.View
- style={[ styles.content,this.props.contentStyle,{ opacity: this.state.opacityAnimate } ]}
- >
- <Text style={[ styles.text,this.props.textStyle ]}>
- { this.state.text }
- </Text>
- </Animated.View>
- </View> : null;
- }
- }
以上代码很简单,基本使用了Animated + View 的方式来实现。最后贴上完整代码:
- const styles = StyleSheet.create({
- container: {
- position: 'absolute',left: 0,right: 0,alignItems: 'center'
- },content: {
- backgroundColor: '#000000',opacity: OPACITY,borderRadius: 20,padding: 10
- },text: {
- color: '#FFFFFF',fontSize: 14,fontFamily: 'PingFang-SC-Regular'
- }
- })
- /**
- * Toast 提示
- */
- import React,{ Component,PropTypes } from 'react';
- import {
- View,Text,Animated,Dimensions,StyleSheet,ViewPropTypes
- } from 'react-native';
- // 设备屏幕宽高
- const { width,height } = Dimensions.get('window');
- // Toast提示框透明度
- const OPACITY = 0.8;
- // 显示时长
- export const DURATION = { LONG: 1500,SHORT: 500 };
- export default class Toast extends Component {
- // 定义props
- static propTypes = {
- textStyle: ViewPropTypes.style,opacityAnimate: new Animated.Value(OPACITY) // 动画 值初始化
- };
- // 当前显示状态
- this.isShow = false;
- // 初始化默认显示时长为SHORT
- this.duration = DURATION.SHORT;
- }
- componentWillUnmount() {
- // 在页面生命周期结束时,解除定时器,避免内存泄漏
- this.animateTimer && clearTimeout(this.animateTimer);
- }
- /**
- * 显示
- */
- show(text,this.duration);
- }
- render() {
- let top;
- switch(this.props.position){
- case 'top':
- top = 30;
- break;
- case 'center':
- top = height / 2;
- break;
- case 'bottom':
- top = height - 100;
- break;
- default:
- break;
- }
- return this.state.isShow ?
- <View
- pointerEvents={ 'none' }
- style={[ styles.container,this.props.textStyle ]}>
- { this.state.text }
- </Text>
- </Animated.View>
- </View> : null;
- }
- }
- const styles = StyleSheet.create({
- container: {
- position: 'absolute',fontFamily: 'PingFang-SC-Regular'
- }
- })
四、使用
1、导入
- import Toast from './components/Toast';
- <Toast ref="toast" position={'bottom'} />
2、调用:
- /**
- * 显示
- */
- showToast() {
- this.refs.toast.show('中奖了...',1200);
- }