react native仿微信PopupWindow效果的实例代码


Posted in Javascript onAugust 07, 2017

在原生APP开发中,相信很多开发者都会见到这种场景:点击右上角更多的选项,弹出一个更多界面供用户选择。这种控件在原生开发中Android可以用PopupWindow实现,在iOS中可以用CMPopTipView,也可以自己写一个View实现。其类似的效果如下图所示:

react native仿微信PopupWindow效果的实例代码

实现思路分析:

要实现上面的视图,有很多种实现方式。前面的文章说过,要实现弹框相关的可以用React Native 提供的 Modal组件(Modal组件),使用Modal组件可以实现我们原生开发中的大多数效果。

要实现下拉三角,可以让美工切一个带下拉三角的背景,当然也可以自己通过ART实现(ART绘制)。对于选项卡的内容,在原生开发中为了适应更多的场景,我们一般会选择使用ListView组件,然后当点击某个Item的时候获得相应的属性即可。为了控制Modal的显示与消失,我们可以给Modal内置一个isVisible: this.props.show状态。

源码

要实现上面的效果,会这涉及到三个js文件:MorePopWidows.js、Utils.js、HomeActionBar.js,按照先后顺序,代码如下:

Utils.js

import {Dimensions} from 'react-native'

const deviceH = Dimensions.get('window').height
const deviceW = Dimensions.get('window').width

const basePx = 375

export default function px2dp(px) { 
  return px * deviceW / basePx
}

MorePopWidows.js

import React from 'react'
import {
  StyleSheet,
  Platform,
  View,
  Text,
  Image,
  TouchableOpacity,
  Alert,
  Modal,
  Dimensions,
} from 'react-native'
import SpacingView from "./SpacingView";
import QRScanPage from "../home/QRScanPage";

const { width, height } = Dimensions.get('window');
import px2dp from '../util/Utils'

const mTop = px2dp(Platform.OS == "ios" ? 64 : 44)

let mwidth = 95;
let mheight = 100;
const marginTop = mTop;

export default class MorePopWidows extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      isVisible: this.props.show,
    }
    mwidth = this.props.width ;
    mheight = this.props.height ;
  }

  componentWillReceiveProps(nextProps) {
    this.setState({ isVisible: nextProps.show });
  }

  closeModal() {
    this.setState({
      isVisible: false
    });
    this.props.closeModal(false);
  }

  scan() {
    this.props.navigator.push({
      component: QRScanPage,
    })
  }

  render() {
    return (
      <View style={styles.container}>
       <Modal
         transparent={true}
         visible={this.state.isVisible}
         animationType={'fade'}
         onRequestClose={() => this.closeModal()}>
        <TouchableOpacity style={styles.container} activeOpacity={1} onPress={() => this.closeModal()}>

         <View style={styles.modal}>
          <TouchableOpacity activeOpacity={1} onPress={this.scan.bind(this)} style={styles.itemView}>
           <Image style={styles.imgStyle} source={require('../images/ic_scan_code_white.png')} />
           <Text style={styles.textStyle}>扫一扫</Text>
          </TouchableOpacity>
           <SpacingView/>
          <TouchableOpacity activeOpacity={1} onPress={() => Alert.alert('点击了付款码')} style={styles.itemView}>
           <Image style={styles.imgStyle} source={require('../images/ic_code_white.png')} />
           <Text style={styles.textStyle}>付款码</Text>
          </TouchableOpacity>
         </View>
        </TouchableOpacity>
       </Modal>
      </View>
    )
  }
}
const styles = StyleSheet.create({
  container: {
    width: width,
    height: height,
  },
  modal: {
    backgroundColor: '#696969',
    width: mwidth,
    height: mheight,
    position: 'absolute',
    left: width - mwidth - 10,
    top: marginTop,
    padding: 5,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 3,
  },
  itemView: {
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    flex: 1,
  },
  textStyle: {
    color: '#fff',
    fontSize: 14,
    marginLeft: 2,
  },
  imgStyle: {
    width: 20,
    height: 20,
  }
});

最后是在代码中使用MorePopWidows的代码:

HomeActionBar.js

/**
 * https://github.com/facebook/react-native
 * @flow 首页的标题栏
 */

import React, {Component} from 'react';
import {Platform, View, Dimensions, Text, StyleSheet, TouchableOpacity, Image} from 'react-native';
import SelectCityPage from '../home/SelectCityPage'
import MorePopWidows from '../component/MorePopWidows'
import px2dp from '../util/Utils'

const isIOS = Platform.OS == "ios"
const {width, height} = Dimensions.get('window')
const headH = px2dp(isIOS ? 64 : 44)

export default class HomeActionBar extends Component {

  constructor(props) {
    super(props);
    this.state = {
      showPop: false,
    }
  }

  city() {
    this.props.navigator.push({
      component: SelectCityPage,
    })
  }

  renderHeader() {
    return (
      <View >
      <View style={styles.headerStyle}>
        <TouchableOpacity style={styles.action} onPress={this.city.bind(this)}>
          <Text style={styles.text}>上海</Text>
          <Image
            source={require('../images/ic_arrow_down.png')}/>
        </TouchableOpacity>
        <TouchableOpacity style={styles.searchBar}>
          <Image source={require('../images/ic_search.png')} style={styles.iconStyle}/>
          <Text style={{fontSize: 13, color: "#666", marginLeft: 5}}>输入商家、商品名称</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.action} onPress={() => { this.setState({ showPop: !this.state.showPop }) }}>
          <Image style={styles.scanIcon}
              source={require('../images/ic_scan_code_white.png')}/>
          <Text style={styles.scanText}>扫码</Text>
        </TouchableOpacity>
      </View>
        <View style={{ position: 'absolute', top: headH, left: 0, width: width, height: height }}>
          <MorePopWidows width={90} height={100} show={this.state.showPop} closeModal={(show) => {
            this.setState({showPop: show})
          }} {...this.props}/>
        </View>

      </View>
    )
  }

  render() {
    return (
      <View>
        {this.renderHeader()}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  headerStyle: {
    backgroundColor: "#06C1AE",
    height: headH,
    paddingTop: px2dp(isIOS ? 20 : 0),
    paddingHorizontal: 16,
    flexDirection: 'row',
    alignItems: 'center',
  },
  searchBar: {
    width: width * 0.65,
    height: 30,
    borderRadius: 19,
    marginLeft: 10,
    flexDirection: 'row',
    justifyContent: 'flex-start',
    alignItems: 'center',
    backgroundColor: 'white',
    alignSelf: 'center',
    paddingLeft: 10,
  },
  text: {
    fontSize: 16,
    color: '#ffffff',
    justifyContent: 'center',
  },
  iconStyle: {
    width: 22,
    height: 22,
  },
  action: {
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
  },
  scanIcon: {
    width: 28,
    height: 28,
    alignItems: 'center',
    marginLeft: 10,
  },
  scanText: {
    fontSize: 14,
    color: '#ffffff',
    justifyContent: 'center',
    alignItems: 'center',
  },
});

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

Javascript 相关文章推荐
增强的 JavaScript 的 trim 函数的代码
Aug 13 Javascript
Jquery日期选择datepicker插件用法实例分析
Jun 08 Javascript
JavaScript采用递归算法计算阶乘实例
Aug 04 Javascript
用JS生成UUID的方法实例
Mar 30 Javascript
jquery 无限极下拉菜单的简单实例(精简浓缩版)
May 31 Javascript
浅谈angularjs $http提交数据探索
Jan 20 Javascript
微信小程序 image组件binderror使用例子与js中的onerror区别
Feb 15 Javascript
javascript将json格式数组下载为excel表格的方法
Dec 22 Javascript
微信小程序 MinUI组件库系列之badge徽章组件示例
Aug 20 Javascript
通过js示例讲解时间复杂度与空间复杂度
Aug 06 Javascript
webpack 处理CSS资源的实现
Sep 27 Javascript
vue ssr服务端渲染(小白解惑)
Nov 10 Javascript
jquery+css实现简单的图片轮播效果
Aug 07 #jQuery
bootstrap table表格客户端分页实例
Aug 07 #Javascript
基于JS递归函数细化认识及实用实例(推荐)
Aug 07 #Javascript
react native实现往服务器上传网络图片的实例
Aug 07 #Javascript
使用Node.js实现简易MVC框架的方法
Aug 07 #Javascript
ES6新增的math,Number方法
Aug 06 #Javascript
ComboBox(下拉列表框)通过url加载调用远程数据的方法
Aug 06 #Javascript
You might like
E路文章系统PHP
2006/12/11 PHP
php session应用实例 登录验证
2009/03/16 PHP
PHP面向对象的进阶学习(抽像类、接口、final、类常量)
2012/05/07 PHP
PHP的构造方法,析构方法和this关键字详细介绍
2013/10/22 PHP
PHP使用NuSOAP调用Web服务的方法
2015/07/18 PHP
PHP实现微信图片上传到服务器的方法示例
2017/06/29 PHP
jquery下操作HTML控件的实现代码
2010/01/12 Javascript
客户端限制只能上传jpg格式图片的js代码
2010/12/09 Javascript
Textarea与懒惰渲染实现代码
2012/01/04 Javascript
实现动画效果核心方式的js代码
2013/09/27 Javascript
无闪烁更新网页内容JS实现
2013/12/19 Javascript
详解AngularJS中$http缓存以及处理多个$http请求的方法
2016/02/06 Javascript
JavaScript实现简单Tip提示框效果
2016/04/20 Javascript
浅析JS异步加载进度条
2016/05/05 Javascript
jquery+ajax实现直接提交表单实例分析
2016/06/17 Javascript
JS遍历ul下的li点击弹出li的索引的实现方法
2016/09/19 Javascript
Javascript中click与blur事件的顺序详析
2017/04/25 Javascript
详解webpack模块加载器兼打包工具
2018/09/11 Javascript
jQuery实现的隔行变色功能【案例】
2019/02/18 jQuery
分享Angular http interceptors 拦截器使用(推荐)
2019/11/10 Javascript
解决elementUI 切换tab后 el_table 固定列下方多了一条线问题
2020/07/19 Javascript
[00:20]TI9观赛名额抽取Ⅱ
2019/07/24 DOTA
Selenium chrome配置代理Python版的方法
2018/11/29 Python
对django中foreignkey的简单使用详解
2019/07/28 Python
Python 词典(Dict) 加载与保存示例
2019/12/06 Python
Java多线程实现四种方式原理详解
2020/06/02 Python
linux面试题参考答案(7)
2014/07/24 面试题
社区中秋节活动方案
2014/01/29 职场文书
小学生检讨书大全
2014/02/06 职场文书
高三家长寄语
2014/04/03 职场文书
校长寄语大全
2014/04/09 职场文书
大学生英语演讲稿
2014/04/24 职场文书
应聘教师求职信
2014/07/19 职场文书
小学竞选班长演讲稿
2014/09/09 职场文书
入党现实表现材料
2014/12/23 职场文书
五年级上册复习计划
2015/01/19 职场文书