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的一些看法
May 27 Javascript
javascript实现的使用方向键控制光标在table单元格中切换
Nov 17 Javascript
javascript AOP 实现ajax回调函数使用比较方便
Nov 20 Javascript
jquery增加和删除元素的方法
Jan 14 Javascript
jquery中ajax使用error调试错误的方法
Feb 08 Javascript
JS实现iframe自适应高度的方法示例
Jan 07 Javascript
详解angular2 控制视图的封装模式
Dec 27 Javascript
vue + axios get下载文件功能
Sep 25 Javascript
jQuery 选择器用法基础入门示例
Jan 04 jQuery
微信小程序仿抖音视频之整屏上下切换功能的实现代码
May 24 Javascript
vue中重定向redirect:‘/index‘,不显示问题、跳转出错的完美解决
Sep 28 Javascript
详解React路由传参方法汇总记录
Nov 29 Javascript
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
如何将数据从文本导入到mysql
2006/10/09 PHP
用PHP动态生成虚拟现实VRML网页
2006/10/09 PHP
php快速url重写更新版[需php 5.30以上]
2010/04/25 PHP
PHP取整数函数常用的四种方法小结
2012/07/05 PHP
php源码分析之DZX1.5加密解密函数authcode用法
2015/06/17 PHP
老生常谈ThinkPHP中的行为扩展和插件(推荐)
2017/05/05 PHP
PHP的new static和new self的区别与使用
2019/11/27 PHP
利用window.name实现windowStorage代码分享
2014/01/02 Javascript
JavaScript判断变量是对象还是数组的方法
2014/08/28 Javascript
浅谈EasyUI中Treegrid节点的删除
2015/03/01 Javascript
js控制网页前进和后退的方法
2015/06/08 Javascript
js实现的二级横向菜单条实例
2015/08/22 Javascript
js实现跨域的4种实用方法原理分析
2015/10/29 Javascript
JS 拦截全局ajax请求实例解析
2016/11/29 Javascript
JS数组操作中的经典算法实例讲解
2017/07/26 Javascript
bootstrap multiselect下拉列表功能
2017/08/22 Javascript
jQuery实现动态显示select下拉列表数据的方法
2018/02/05 jQuery
Node.js爬取豆瓣数据实例分析
2018/03/05 Javascript
原生js实现form表单序列化的方法
2018/08/02 Javascript
微信小程序实现多选功能
2018/11/04 Javascript
关于JS模块化的知识点分享
2019/10/16 Javascript
[50:28]LGD女子学院第三期 DOTA2复仇之魂教学
2013/12/24 DOTA
利用pyinstaller将py文件打包为exe的方法
2018/05/14 Python
Python django框架应用中实现获取访问者ip地址示例
2019/05/17 Python
解决django后台样式丢失,css资源加载失败的问题
2019/06/11 Python
Python中Unittest框架的具体使用
2019/08/27 Python
Python3和PyCharm安装与环境配置【图文教程】
2020/02/14 Python
python中取绝对值简单方法总结
2020/07/24 Python
会计应聘求职信范文
2013/12/17 职场文书
期末自我鉴定
2014/02/02 职场文书
教师敬业奉献模范事迹材料
2014/05/18 职场文书
旅游专业毕业生自荐书
2014/06/30 职场文书
环保项目建议书
2014/08/26 职场文书
党员个人年度总结
2015/02/14 职场文书
Golang 实现超大文件读取的两种方法
2021/04/27 Golang
《乙女游戏世界对路人角色很不友好》OP主题曲无字幕动画MV公开
2022/04/05 日漫