react-native 封装选择弹出框示例(试用ios&android)


Posted in Javascript onJuly 11, 2017

在开发 App 的时候,经常会使用到对话框(又叫消息框、提示框、告警框)。 在web开发中经常会用得到。今天就来介绍了一下react-native 封装弹出框

之前看到react-native-image-picker中自带了一个选择器,可以选择拍照还是图库,但我们的项目中有多处用到这个选择弹出框,所以就自己写了一下,最最重要的是ios和Android通用。先上动态效果图~

react-native 封装选择弹出框示例(试用ios&android)

一、封装要点

1.使用动画实现弹框布局及显示隐藏效果

2.通过一个boolean值控制组件的显示隐藏

3.弹框选项数组通过调用的js传到弹框组件

4.组件选项的字体颜色通过调用js传到组件,实现可拓展;

5.选择选项回调方法

二、代码实现

新建alertSelected.js

/**
 * Created by sybil052 on 2017/6/19.
 */
import React, {Component} from 'react';
import {
  StyleSheet,
  View,
  Image,
  Text,
  TouchableHighlight,
  Animated,
  Easing,
  Dimensions,
  Platform,
  TouchableOpacity
} from 'react-native';

const {width, height} = Dimensions.get('window');
const [aWidth] = [width-20];
const [left, top] = [0, 0];
const [middleLeft] = [(width - aWidth) / 2];

export default class AlertSelected extends Component {
  constructor(props) {
    super(props);
    this.state = {
      offset: new Animated.Value(0),
      opacity: new Animated.Value(0),
      title: "",
      choose0: "",
      choose1: "",
      hide: true,
      tipTextColor: '#333333',
      aHeight: 236,
    };
    this.entityList = [];//数据源
    this.callback = function () {
    };//回调方法
  }

  render() {
    if (this.state.hide) {
      return (<View />)
    } else {
      return (
        <View style={styles.container}>
          <Animated.View style={styles.mask}>
          </Animated.View>

          <Animated.View style={[{
            width: aWidth,
            height: this.state.aHeight,
            left: middleLeft,
            ...Platform.select({
              ios:{
                bottom: - 20,
              },
            }),
            alignItems: "center",
            justifyContent: "space-between",
          }, {
            transform: [{
              translateY: this.state.offset.interpolate({
                inputRange: [0, 1],
                outputRange: [height, (height - this.state.aHeight - 34)]
              }),
            }]
          }]}>
            <View style={styles.content}>
            <View style={styles.tipTitleView}>
              <Text style={styles.tipTitleText}>{this.state.title}</Text>
            </View>
            {
              this.entityList.map((item, i) => this.renderItem(item, i))
            }
            </View>
            <TouchableHighlight
              style={styles.button}
              underlayColor={'#f0f0f0'}
              onPress={this.cancel.bind(this)}
            >
              <Text style={styles.buttonText}>取消</Text>
            </TouchableHighlight>
          </Animated.View>
        </View>
      );
    }
  }

  renderItem(item, i) {
    return (
      <View style={styles.tipContentView}>
        <View style={{height: 0.5, backgroundColor: '#a9a9a9', width: aWidth}}/>
        <TouchableOpacity
        key={i}
        onPress={this.choose.bind(this, i)}
      >
          <View style={styles.item}>
            <Text style={{
              color: this.state.tipTextColor,
              fontSize: 17,
              textAlign: "center",
            }}>{item}</Text>
          </View>
        </TouchableOpacity>
      </View>
    );
  }

  componentDidMount() {
  }

  componentWillUnmount() {
    // 如果存在this.timer,则使用clearTimeout清空。
    // 如果你使用多个timer,那么用多个变量,或者用个数组来保存引用,然后逐个clear
    this.timer && clearTimeout(this.timer);
    this.chooseTimer && clearTimeout(this.chooseTimer);
  }

  //显示动画
  in() {
    Animated.parallel([
      Animated.timing(
        this.state.opacity,
        {
          easing: Easing.linear,//一个用于定义曲线的渐变函数
          duration: 200,//动画持续的时间(单位是毫秒),默认为200。
          toValue: 0.8,//动画的最终值
        }
      ),
      Animated.timing(
        this.state.offset,
        {
          easing: Easing.linear,
          duration: 200,
          toValue: 1,
        }
      )
    ]).start();
 }

  //隐藏动画
  out() {
    Animated.parallel([
      Animated.timing(
        this.state.opacity,
        {
          easing: Easing.linear,
          duration: 200,
          toValue: 0,
        }
      ),
      Animated.timing(
        this.state.offset,
        {
          easing: Easing.linear,
          duration: 200,
          toValue: 0,
        }
      )
    ]).start((finished) => this.setState({hide: true}));
  }

  //取消
  cancel(event) {
    if (!this.state.hide) {
      this.out();
    }
  }

  //选择
  choose(i) {
    if (!this.state.hide) {
      this.out();
      this.chooseTimer = setTimeout(()=>{
        this.callback(i);
      }, 200);
    }
  }

 /**
 * 弹出控件,最多支持3个选项(包括取消)
 * titile: 标题
 * entityList:选择项数据  数组
 * tipTextColor: 字体颜色
 * callback:回调方法
 */
 show(title: string, entityList: Array, tipTextColor: string, callback: Object) {
   this.entityList = entityList;
   this.callback = callback;

   if (this.state.hide) {
     if (entityList && entityList.length > 0) {
       let len = entityList.length;
       if (len === 1) {
         this.setState({title: title, choose0: entityList[0], hide: false, tipTextColor: tipTextColor, aHeight: 180}, this.in);
       } else if (len === 2) {
         this.setState({title: title, choose0: entityList[0], choose1: entityList[1], hide: false, tipTextColor: tipTextColor, aHeight: 236}, this.in);
       }
     }
   }
 }
}

const styles = StyleSheet.create({
  container: {
    position: "absolute",
    width: width,
    height: height,
    left: left,
    top: top,
  },
  mask: {
    justifyContent: "center",
    backgroundColor: "#000000",
    opacity: 0.3,
    position: "absolute",
    width: width,
    height: height,
    left: left,
    top: top,
  },
  // 提示标题
  tipTitleView: {
    height: 56,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#fff',
    marginLeft: 10,
    marginRight: 10
  },
  // 提示文字
  tipTitleText: {
    color: "#999999",
    fontSize: 14,
  },
  // 分割线
  tipContentView: {
    width: aWidth,
    height: 56,
    backgroundColor:'#fff',
    borderBottomLeftRadius: 5,
    borderBottomRightRadius: 5,
  },
  item:{
    width: aWidth,
    height: 56,
    backgroundColor:'#fff',
    justifyContent: 'center',
    borderRadius: 5,
  },
  button: {
    height: 57,
    backgroundColor: '#fff',
    alignSelf: 'stretch',
    justifyContent: 'center',
    borderRadius: 5,
  },
  // 取消按钮
  buttonText: {
    fontSize: 17,
    color: "#0084ff",
    textAlign: "center",
  },
  content: {
    backgroundColor: '#fff',
    borderRadius: 5,
  }
});

三、使用方法

新建demo.js

const selectedArr = ["拍照", "图库"];
class Demo extends Component {
  constructor(props) {
    super(props);
    this.showAlertSelected = this.showAlertSelected.bind(this);
    this.callbackSelected = this.callbackSelected.bind(this);
  }

  showAlertSelected(){
    this.dialog.show("请选择照片", selectedArr, '#333333', this.callbackSelected);
  }
  // 回调
  callbackSelected(i){
    switch (i){
      case 0: // 拍照
        this.takePhoto();
        break;
      case 1: // 图库
        this.pickMultiple();
        break;
    }
  }
  render() {
    return (
      <View style={stylesCommon.container}>
        <TouchableOpacity onPress={() => {this.showAlertSelected();}}>
          <View style={styles.imageBorder}>
            <Text style={styles.photoText}>?</Text>
          </View>
        </TouchableOpacity>
        <DialogSelected ref={(dialog)=>{
          this.dialog = dialog;
        }} /> 
      </View>
    );
  } 
}

再来一张其他界面调用该组件的效果图~

react-native 封装选择弹出框示例(试用ios&amp;android)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript编程起步(第七课)
Jan 10 Javascript
使用新的消息弹出框blackbirdjs
Oct 16 Javascript
在JavaScript中使用timer示例
May 08 Javascript
使用ajax+jqtransform实现动态加载select
Dec 01 Javascript
jQuery+PHP实现微信转盘抽奖功能的方法
May 25 Javascript
详解vue2路由vue-router配置(懒加载)
Apr 08 Javascript
angular.js指令中transclude选项及ng-transclude指令详解
May 24 Javascript
基于Vue的文字跑马灯组件(npm 组件包)
May 24 Javascript
JavaScript常见事件处理程序实例总结
Jan 05 Javascript
浅谈Vue SSR中的Bundle的具有使用
Nov 21 Javascript
js实现弹框效果
Mar 24 Javascript
Vue实现下拉加载更多
May 09 Vue.js
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
Jul 11 #Javascript
javascript 玩转Date对象(实例讲解)
Jul 11 #Javascript
使用jQuery实现动态添加小广告
Jul 11 #jQuery
Vue中父组件向子组件通信的方法
Jul 11 #Javascript
实例讲解DataTables固定表格宽度(设置横向滚动条)
Jul 11 #Javascript
网页中的图片查看器viewjs使用方法
Jul 11 #Javascript
自定义事件解决重复请求BUG的问题
Jul 11 #Javascript
You might like
php 购物车实例(申精)
2009/05/11 PHP
php ci框架中加载css和js文件失败的解决方法
2014/03/03 PHP
PHP 正则表达式小结
2015/02/12 PHP
浅谈php和js中json的编码和解码
2016/10/24 PHP
基于jquery的复制网页内容到WORD的实现代码
2011/02/16 Javascript
关于跨站脚本攻击问题
2011/12/22 Javascript
拉动滚动条加载数据的jquery代码
2012/05/03 Javascript
JS的replace方法详细介绍
2012/11/09 Javascript
文本框只能选择数据到文本框禁止手动输入
2013/11/22 Javascript
使用jQuery获得内容以及内容的属性
2015/02/26 Javascript
简单谈谈javascript Date类型
2015/09/06 Javascript
Jquery全屏相册插件zoomvisualizer具有调节放大与缩小功能
2015/11/02 Javascript
vue实现添加标签demo示例代码
2017/01/21 Javascript
原生JavaScript实现AJAX、JSONP
2017/02/07 Javascript
jquery实现左右滑动式轮播图
2017/03/02 Javascript
深入nodejs中流(stream)的理解
2017/03/27 NodeJs
Javascript调试之console对象——你不知道的一些小技巧
2017/07/10 Javascript
Vue监听数据渲染DOM完以后执行某个函数详解
2018/09/11 Javascript
解决Vue中引入swiper,在数据渲染的时候,发生不滑动的问题
2018/09/27 Javascript
优雅的在React项目中使用Redux的方法
2018/11/10 Javascript
JS实现按比例缩小图片宽高
2020/08/24 Javascript
详解JavaScript中的数据类型,以及检测数据类型的方法
2020/09/17 Javascript
python使用rsa加密算法模块模拟新浪微博登录
2014/01/22 Python
python中子类调用父类函数的方法示例
2017/08/18 Python
python监控键盘输入实例代码
2018/02/09 Python
Python带动态参数功能的sqlite工具类
2018/05/26 Python
Pandas 同元素多列去重的实例
2018/07/03 Python
Python利用递归实现文件的复制方法
2018/10/27 Python
python广度优先搜索得到两点间最短路径
2019/01/17 Python
低碳环保标语
2014/06/12 职场文书
2014国庆65周年领导讲话稿(3篇)
2014/09/21 职场文书
基层党员干部四风问题整改方向和措施
2014/09/25 职场文书
2015年毕业生个人自荐书
2015/03/24 职场文书
2016年离婚协议书范文
2016/03/18 职场文书
python使用openpyxl库读写Excel表格的方法(增删改查操作)
2021/05/02 Python
关于Redis的主从复制及哨兵问题
2022/06/16 Redis