本文共 4255 字,大约阅读时间需要 14 分钟。
http://blog.csdn.net/column/details/reactnative2016.html?&page=1
最近在项目中封装了个Dialog组件,和平台上通用。
组件Dialog显示时,从页面顶部滑动到中间,点击确认或取消后,从页面底部划出页面,需要注意动画的实现。
源码如下:
- 'use strict';
- import React, { Component } from 'react';
- import {
- StyleSheet,
- View,
- Image,
- Text,
- TouchableHighlight,
- Animated,
- Easing,
- Dimensions,
- } from 'react-native';
-
- import TimerMixin from 'react-timer-mixin';
-
- const {width, height} = Dimensions.get('window');
- const navigatorH = 64;
- const [aWidth, aHeight] = [270, 108];
- const [left, top] = [0, 0];
- const [middleLeft, middleTop] = [(width - aWidth) / 2, (height - aHeight) / 2 - navigatorH];
-
-
-
-
-
-
-
- export default class Dialog extends Component {
- mixins = [TimerMixin];
- parent ={};
-
-
- constructor(props) {
- super(props);
- this.state = {
- offset: new Animated.Value(0),
- opacity: new Animated.Value(0),
- title: "",
- hide: true,
- };
- }
-
- render() {
- if(this.state.hide){
- return (<View />)
- } else {
- return (
- <View style={styles.container} >
- <Animated.View style={ styles.mask } >
- </Animated.View>
-
- <Animated.View style={[styles.tip , {transform: [{
- translateY: this.state.offset.interpolate({
- inputRange: [0, 1,2],
- outputRange: [0, middleTop,height]
- }),
- }]
- }]}>
- <View style={styles.tipTitleView}>
- <Text style={styles.tipTitleText}>{ this.state.title}</Text>
- </View>
-
- <View style={styles.btnView}>
- <TouchableHighlight style={styles.cancelBtnView} underlayColor='#f0f0f0' onPress={ this.cancelBtn.bind(this)}>
- <Text style={styles.cancelBtnText}>取消</Text>
- </TouchableHighlight>
- <TouchableHighlight style={styles.okBtnView} underlayColor='#f0f0f0' onPress={ this.okBtn.bind(this)}>
- <Text style={styles.okBtnText}>确定</Text>
- </TouchableHighlight>
- </View>
- </Animated.View>
- </View>
- );
- }
- }
-
-
-
- in() {
- Animated.parallel([
- Animated.timing(
- this.state.opacity,
- {
- easing: Easing.linear,
- duration: 500,
- toValue: 0.8,
- }
- ),
- Animated.timing(
- this.state.offset,
- {
- easing: Easing.linear,
- duration: 500,
- toValue: 1,
- }
- )
- ]).start();
- }
-
-
- out(){
- Animated.parallel([
- Animated.timing(
- this.state.opacity,
- {
- easing: Easing.linear,
- duration: 500,
- toValue: 0,
- }
- ),
- Animated.timing(
- this.state.offset,
- {
- easing: Easing.linear,
- duration: 500,
- toValue: 2,
- }
- )
- ]).start();
-
- setTimeout(
- () => {
- this.setState({hide: true});
-
- Animated.timing(
- this.state.offset,
- {
- easing: Easing.linear,
- duration: 500,
- toValue: 0,
- }
- ).start();
- },
- 500
- );
- }
-
-
- cancelBtn(event) {
- if(!this.state.hide){
- this.out();
- }
- }
-
-
-
-
-
-
- okBtn() {
- if(!this.state.hide){
- this.out();
- setTimeout(
- () => {
- let {callback} = this.props;
- callback.apply(null,[]);
- },
- 500
- );
- }
- }
-
-
-
-
-
- show(title: string) {
- if(this.state.hide){
- this.setState({title: title, hide: false}, this.in);
- }
- }
- }
-
- const styles = StyleSheet.create({
- container: {
- position:"absolute",
- width:width,
- height:height,
- left:left,
- top:top,
- },
- mask: {
- justifyContent:"center",
- backgroundColor:"#383838",
- opacity:0.8,
- position:"absolute",
- width:width,
- height:height,
- left:left,
- top:top,
- },
- tip: {
- width:aWidth,
- height:aHeight,
- left:middleLeft,
- backgroundColor:"#fff",
- alignItems:"center",
- justifyContent:"space-between",
- },
- tipTitleView: {
- width:aWidth,
- flexDirection:'row',
- alignItems:'center',
- justifyContent:'center',
- borderBottomWidth:1/2,
- borderColor:'#f0f0f0',
- },
- tipTitleText:{
- color:"#333333",
- fontSize:17,
- marginTop:28,
- marginBottom:19,
- textAlignVertical:'center',
- textAlign:'center',
- },
-
- btnView:{
- flexDirection:'row',
- height: 44,
- },
- cancelBtnView:{
- width:aWidth/2,
- height: 44,
- backgroundColor: '#fff',
- alignItems: 'center',
- justifyContent: 'center',
- borderRightWidth:1/2,
- borderColor:'#f0f0f0',
- },
- cancelBtnText: {
- fontSize:17,
- color:"#e6454a",
- textAlign:"center",
- fontWeight:'bold',
- },
- okBtnView:{
- width:aWidth/2,
- height: 44,
- backgroundColor: '#fff',
- alignItems: 'center',
- justifyContent: 'center',
- },
- okBtnText: {
- fontSize:17,
- color:"#e6454a",
- textAlign:"center",
- },
-
- });
如果需要使用该组件,只需要3步即可:
1、在你的页面import 组件,加入代码:
- <Dialog ref="dialog" callback={ this.callback.bind(this)}/>
2、自定义回调方法callback,处理选中逻辑
3、调用show方法
- 调用show方法,调起组件 this.refs.dialog.show("确定要取消订单吗");
备注:组件的样式可以根据你的需求修改,组件的动画也可以修改。
组件效果如下: