ReactNative实战系列 组件封装之Dialog(iOS和Android通用)

来源:互联网 发布:单倍型分析软件 编辑:程序博客网 时间:2024/06/05 21:05

http://blog.csdn.net/column/details/reactnative2016.html?&page=1

《React-Native系列》1、初探React-Native

《React-Native系列》2、RN与native交互与数据传递

《React-Native系列》3、RN与native交互之Callback、Promise

《React-Native系列》4、表单界面代码编写

《React-Native系列》5、RN实现弹出选择界面与动画效果

《React-Native系列》6、Navigator语法介绍及经典应用

《React-Native系列》7、bundle文件的加载和维护

《React-Native系列》8、RN如何打离线包

《React-Native系列》9、 Networking之fetch

《React-Native系列》10、 RN组件之Text和TextInput以及注意要点

《React-Native系列》11、 图解RN布局之FlexBox,三分钟上手写RN界面

《React-Native系列》12、 API模块之PixelRatio和Dimensions

《React-Native系列》13、 组件封装之Dialog(iOS和Android通用)

《React-Native系列》14、 RN学习之NodeJS

《React-Native系列》15、 RN之可触摸组件

《React-Native系列》16、 RN组件之ListView

《React-Native系列》17、 RN中this所引起的undefined is not an object错误

《React-Native系列》18、 RN之定时器Timer

《React-Native系列》19、 ListView组件之上拉刷新(iOS和Android通用)

《React-Native系列》20、 RN数据流之Flux概览

《React-Native系列》21、 解决RN在Android下不支持gif问题

《React-Native系列》22、 Flux框架Demo详解

《React-Native系列》23、 js实现下拉刷新效果(Android和iOS通用)

《React-Native系列》24、 结合Demo学习Redux框架

《React-Native系列》25、 详解Redux的connect方法

《React-Native系列》26、 ReactNative实现图片上传功能

《React-Native系列》27、 Redux的异步数据流

《React-Native系列》28、 RN之AsyncStorage

《React-Native系列》29、 RN组件之WebView

《React-Native系列》30、 RN组件间通信

《React-Native系列》31、 Fetch发送POST请求的坑与解决方案

《React-Native系列》32、 基于Fetch封装HTTPUtil工具类

《React-Native系列》33、 键盘遮挡问题处理

《React-Native系列》34、 ReactNative的那些坑

《React-Native系列》35、 RN在Android下支持gif的另一种方案

《React-Native系列》36、 ReactNative地图组件

《React-Native系列》37、 ReactNative百度地图开源组件使用

《React-Native系列》38、 ReactNative混合组件封装

《React-Native系列》39、 ReactNative之键盘Keyboard

《React-Native系列》40、 ReactNative之bundle文件瘦身

《React-Native系列》41、刨根问底Picker组件

《React-Native系列》42、键盘遮挡问题官方处理方法KeyboardAvoidingView

《React-Native系列》43、通用容器和导航设计方案

《React-Native系列》44、基于多个TextInput的键盘遮挡处理方案优化

《React-Native系列》45、踩坑记录

《React-Native系列》React-Native实战系列博客汇总



最近在项目中封装了个Dialog组件,iOS和Android平台上通用。

组件Dialog显示时,从页面顶部滑动到中间,点击确认或取消后,从页面底部划出页面,需要注意动画的实现。


源码如下:

[javascript] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 'use strict';  
  2. import React, { Component } from 'react';  
  3. import {  
  4.   StyleSheet,  
  5.   View,  
  6.   Image,  
  7.   Text,  
  8.   TouchableHighlight,  
  9.   Animated,  
  10.   Easing,  
  11.   Dimensions,  
  12. } from 'react-native';  
  13.   
  14. import TimerMixin from 'react-timer-mixin';  
  15.   
  16. const {width, height} = Dimensions.get('window');  
  17. const navigatorH = 64; // navigator height  
  18. const [aWidth, aHeight] = [270, 108];  
  19. const [left, top] = [0, 0];  
  20. const [middleLeft, middleTop] = [(width - aWidth) / 2, (height - aHeight) / 2 - navigatorH];  
  21.   
  22. /** 
  23. * Dialog组件 
  24. * <Dialog ref="dialog" callback={this.callback.bind(this)}/> 
  25. * 调用show方法,调起组件   this.refs.dialog.show("确定删除吗"); 
  26. */  
  27.   
  28. export default class Dialog extends Component {  
  29.   mixins = [TimerMixin];  
  30.   parent ={};  
  31.   
  32.   
  33.   constructor(props) {  
  34.     super(props);  
  35.     this.state = {  
  36.       offset: new Animated.Value(0),  
  37.       opacity: new Animated.Value(0),  
  38.       title: "",  
  39.       hide: true,  
  40.     };  
  41.   }  
  42.   
  43.   render() {  
  44.     if(this.state.hide){  
  45.       return (<View />)  
  46.     } else {  
  47.       return (  
  48.         <View style={styles.container} >  
  49.           <Animated.View style={ styles.mask } >  
  50.           </Animated.View>  
  51.   
  52.           <Animated.View style={[styles.tip , {transform: [{  
  53.                 translateY: this.state.offset.interpolate({  
  54.                  inputRange: [0, 1,2],  
  55.                  outputRange: [0, middleTop,height]  
  56.                 }),  
  57.               }]  
  58.             }]}>  
  59.             <View style={styles.tipTitleView}>  
  60.               <Text style={styles.tipTitleText}>{this.state.title}</Text>  
  61.             </View>  
  62.   
  63.             <View style={styles.btnView}>  
  64.               <TouchableHighlight style={styles.cancelBtnView} underlayColor='#f0f0f0' onPress={this.cancelBtn.bind(this)}>  
  65.                 <Text style={styles.cancelBtnText}>取消</Text>  
  66.               </TouchableHighlight>  
  67.               <TouchableHighlight style={styles.okBtnView} underlayColor='#f0f0f0' onPress={this.okBtn.bind(this)}>  
  68.                 <Text style={styles.okBtnText}>确定</Text>  
  69.               </TouchableHighlight>  
  70.             </View>  
  71.           </Animated.View>  
  72.         </View>  
  73.       );  
  74.     }  
  75.   }  
  76.   
  77.   
  78.   //显示动画  
  79.   in() {  
  80.     Animated.parallel([  
  81.       Animated.timing(  
  82.         this.state.opacity,  
  83.         {  
  84.           easing: Easing.linear,  
  85.           duration: 500,  
  86.           toValue: 0.8,  
  87.         }  
  88.       ),  
  89.       Animated.timing(  
  90.         this.state.offset,  
  91.         {  
  92.           easing: Easing.linear,  
  93.           duration: 500,  
  94.           toValue: 1,  
  95.         }  
  96.       )  
  97.     ]).start();  
  98.   }  
  99.   
  100.   //隐藏动画  
  101.   out(){  
  102.     Animated.parallel([  
  103.       Animated.timing(  
  104.         this.state.opacity,  
  105.         {  
  106.           easing: Easing.linear,  
  107.           duration: 500,  
  108.           toValue: 0,  
  109.         }  
  110.       ),  
  111.       Animated.timing(  
  112.         this.state.offset,  
  113.         {  
  114.           easing: Easing.linear,  
  115.           duration: 500,  
  116.           toValue: 2,  
  117.         }  
  118.       )  
  119.     ]).start();  
  120.   
  121.     setTimeout(  
  122.       () => {  
  123.         this.setState({hide: true});  
  124.         //还原到顶部  
  125.         Animated.timing(  
  126.           this.state.offset,  
  127.           {  
  128.             easing: Easing.linear,  
  129.             duration: 500,  
  130.             toValue: 0,  
  131.           }  
  132.         ).start();  
  133.       },  
  134.       500  
  135.     );  
  136.   }  
  137.   
  138.   //取消  
  139.   cancelBtn(event) {  
  140.     if(!this.state.hide){  
  141.       this.out();  
  142.     }  
  143.   }  
  144.   
  145.   // doCallback(fn,args){  
  146.   //   fn.apply(this.parent, args);  
  147.   // }  
  148.   
  149.   //选择  
  150.   okBtn() {  
  151.     if(!this.state.hide){  
  152.       this.out();  
  153.       setTimeout(  
  154.         () => {  
  155.           let {callback} = this.props;  
  156.           callback.apply(null,[]);  
  157.         },  
  158.         500  
  159.       );  
  160.     }  
  161.   }  
  162.   
  163.   /** 
  164.   * 弹出控件 
  165.   * titile: 标题 
  166.   */  
  167.   show(title: string) {  
  168.     if(this.state.hide){  
  169.       this.setState({title: title, hide: false}, this.in);  
  170.     }  
  171.   }  
  172. }  
  173.   
  174. const styles = StyleSheet.create({  
  175.   container: {  
  176.     position:"absolute",  
  177.     width:width,  
  178.     height:height,  
  179.     left:left,  
  180.     top:top,  
  181.   },  
  182.   mask: {  
  183.     justifyContent:"center",  
  184.     backgroundColor:"#383838",  
  185.     opacity:0.8,  
  186.     position:"absolute",  
  187.     width:width,  
  188.     height:height,  
  189.     left:left,  
  190.     top:top,  
  191.   },  
  192.   tip: {  
  193.     width:aWidth,  
  194.     height:aHeight,  
  195.     left:middleLeft,  
  196.     backgroundColor:"#fff",  
  197.     alignItems:"center",  
  198.     justifyContent:"space-between",  
  199.   },  
  200.   tipTitleView: {  
  201.     width:aWidth,  
  202.     flexDirection:'row',  
  203.     alignItems:'center',  
  204.     justifyContent:'center',  
  205.     borderBottomWidth:1/2,  
  206.     borderColor:'#f0f0f0',  
  207.   },  
  208.   tipTitleText:{  
  209.     color:"#333333",  
  210.     fontSize:17,  
  211.     marginTop:28,  
  212.     marginBottom:19,  
  213.     textAlignVertical:'center',  
  214.     textAlign:'center',  
  215.   },  
  216.   
  217.   btnView:{  
  218.     flexDirection:'row',  
  219.     height: 44,  
  220.   },  
  221.   cancelBtnView:{  
  222.     width:aWidth/2,  
  223.     height: 44,  
  224.     backgroundColor: '#fff',  
  225.     alignItems: 'center',  
  226.     justifyContent: 'center',  
  227.     borderRightWidth:1/2,  
  228.     borderColor:'#f0f0f0',  
  229.   },  
  230.   cancelBtnText: {  
  231.     fontSize:17,  
  232.     color:"#e6454a",  
  233.     textAlign:"center",  
  234.     fontWeight:'bold',  
  235.   },  
  236.   okBtnView:{  
  237.     width:aWidth/2,  
  238.     height: 44,  
  239.     backgroundColor: '#fff',  
  240.     alignItems: 'center',  
  241.     justifyContent: 'center',  
  242.   },  
  243.   okBtnText: {  
  244.     fontSize:17,  
  245.     color:"#e6454a",  
  246.     textAlign:"center",  
  247.   },  
  248.   
  249. });  

如果需要使用该组件,只需要3步即可:

1、在你的页面import 组件,加入代码:

[javascript] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <Dialog ref="dialog" callback={this.callback.bind(this)}/>  

2、自定义回调方法callback,处理选中逻辑

3、调用show方法

[javascript] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 调用show方法,调起组件   this.refs.dialog.show("确定要取消订单吗");  

备注:组件的样式可以根据你的需求修改,组件的动画也可以修改。


组件效果如下:

0 0