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

来源:互联网 发布:编程原本 pdf 下载 编辑:程序博客网 时间:2024/05/21 06:30

今天做了个弹出框,见文章最后图片所示,弹出的时候从屏幕下方弹入,用户选择后又从下方弹出,同时有遮罩效果。

首先,我们是怎么实现弹出框,我这边用的是absolute 绝对定位,包括弹层的覆盖,Dialog的绝对位置。

Dialog的布局在这儿就不说了,flex-box、盒子模型...

那么再来说说动画。

参考:RN动画入门Animated


1、创建一个Animated.Value

          <Animated.View style={ styles.mask } >          </Animated.View>          <Animated.View style={[styles.tip , {transform: [{                translateY: this.state.offset.interpolate({                 inputRange: [0, 1],                 outputRange: [height, (height-aHeight -34)]                }),              }]            }]}>         </Animated.View>

我这里创建了2个,一个是遮罩效果,一个是dialog。


2、Dialog样式编写

 此处略,见后面完整代码。

3、动画效果

首先是显示Dialog的动画:

  //显示动画  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();  }

动画还可以被更复杂地组合,通过一些辅助函数例如sequence或者parallel(它们分别用于先后执行多个动画和同时执行多个动画)

由于我里设计成了2组动画,所以使用了parallel让他们同时执行。

duration:执行时间

easing:Easing的枚举值如下

  spring  //弹跳  linear  //线性  easeInEaseOut  //缓入缓出  easeIn  //缓入  easeOut  //缓出  keyboard  //键入

介绍下 interpolate ,官网上说明如下:

interpolate(config: InterpolationConfigType) 

在更新属性之前对值进行插值。譬如:把0-1映射到0-10。


在这儿我们在translateY 输入从0到1,高度从height 到 (height-aHeight -34),只是简单的让Dialog在Y方式上移动。


明白了显示动画的原理,动画消失就更简单了。

原理:遮罩层由 0.8的透明度变味 0(不显示),高度再反过来就行(从哪里来,回哪里去) ,代码见下面。


最终实现的效果如下:



完整代码如下:(这里把Dialog封装成了组件,需要使用的话, 在你的页面直接导入,然后通过ref 的方式调用show方法即可)

当然你也可以根据你的需求,修改样式。这里只是说明了一种实现方案。

'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; // navigator heightconst [aWidth, aHeight] = [300, 214];const [left, top] = [0, 0];const [middleLeft, middleTop] = [(width - aWidth) / 2, (height - aHeight) / 2 - navigatorH];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: {    height:55,    flexDirection:'row',    alignItems:'center',    justifyContent:'center',  },  tipTitleText:{    color:"#999999",    fontSize:14,  },  tipContentView: {    width:aWidth,    borderTopWidth:0.5,    borderColor:"#f0f0f0",    height:45,    flexDirection:'row',    alignItems:'center',    justifyContent:'center',  },  tipText:{    color:"#e6454a",    fontSize:17,    textAlign:"center",  },  button: {    height: 45,    backgroundColor: '#fff',    //borderColor: '#e6454a',    //borderWidth: 1,    //borderRadius: 4,    alignSelf: 'stretch',    justifyContent: 'center',    //marginLeft: 10,    //marginRight: 10,  },  buttonText: {    fontSize:17,    color:"#e6454a",    textAlign:"center",  },  gap:{    height:10,    width:aWidth,    backgroundColor:'#383838',    opacity:0.8,  },});//console.log('======');export default class Alert extends Component {  mixins = [TimerMixin];  parent ={};  constructor(props) {    super(props);    this.state = {      offset: new Animated.Value(0),      opacity: new Animated.Value(0),      title: "",      choose1: "",      choose2: "",      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],                 outputRange: [height, (height-aHeight -34)]                }),              }]            }]}>            <View style={styles.tipTitleView}>              <Text style={styles.tipTitleText}>{this.state.title}</Text>            </View>            <TouchableHighlight style={styles.tipContentView} underlayColor='#f0f0f0' onPress={this.choose.bind(this,this.state.choose1)}>              <Text style={styles.tipText} >{this.state.choose1}</Text>            </TouchableHighlight>            <TouchableHighlight style={styles.tipContentView} underlayColor='#f0f0f0' onPress={this.choose.bind(this,this.state.choose2)}>              <Text style={styles.tipText} >{this.state.choose2}</Text>            </TouchableHighlight>            <View style={styles.gap}/>            <TouchableHighlight style={styles.button} underlayColor='#f0f0f0' onPress={this.iknow.bind(this)}>              <Text style={styles.buttonText}>取消</Text>            </TouchableHighlight>          </Animated.View>        </View>      );    }  }  componentDidMount() {  }  //显示动画  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: 0,        }      )    ]).start();    setTimeout(      () => this.setState({hide: true}),      500    );  }  //取消  iknow(event) {    if(!this.state.hide){      this.out();    }  }  //选择  choose(msg) {    //console.log(msg);    if(!this.state.hide){      this.out();      this.parent.setState({sex:msg});    }  }  show(title: string, choose1:string,choose2:string ,obj:Object) {    this.parent = obj;    if(this.state.hide){      this.setState({title: title, choose1: choose1, choose2: choose2, hide: false}, this.in);    }  }}



5 0
原创粉丝点击