欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-05-26 09:01:56
在开发 app 的时候,经常会使用到对话框(又叫消息框、提示框、告警框)。 在web开发中经常会用得到。今天就来介绍了一下react-native 封装弹出框 之前看...

在开发 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&android)

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