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 相关文章推荐
关于document.cookie的使用javascript
Apr 11 Javascript
JS无限树状列表实现代码
Jan 11 Javascript
对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!
Oct 29 Javascript
Javascript生成json的函数代码(可以用php的json_decode解码)
Jun 11 Javascript
js中判断Object、Array、Function等引用类型对象是否相等
Aug 29 Javascript
浅析XMLHttpRequest的缓存问题
Dec 13 Javascript
JS日期加减,日期运算代码
Nov 05 Javascript
js获取时间精确到秒(年月日)
Mar 16 Javascript
javascript设计模式之Adapter模式【适配器模式】实现方法示例
Jan 13 Javascript
Vue2.5学习笔记之如何在项目中使用和配置Vue
Sep 26 Javascript
Vue3.0数据响应式原理详解
Oct 09 Javascript
vue深度监听(监听对象和数组的改变)与立即执行监听实例
Sep 04 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
PHP实现留言板功能的详细代码
2017/03/25 PHP
ie 处理 gif动画 的onload 事件的一个 bug
2007/04/12 Javascript
IE与Firefox在JavaScript上的7个不同写法小结
2009/09/14 Javascript
为radio类型的INPUT添加客户端脚本(附加实现JS来禁用onClick事件思路代码)
2010/11/11 Javascript
Area 区域实现post提交数据的js写法
2014/04/22 Javascript
浅析jQuery Mobile的初始化事件
2015/12/03 Javascript
阻止表单提交按钮多次提交的完美解决方法
2016/05/16 Javascript
jQuery的each循环用法简单示例
2016/06/12 Javascript
分享jQuery封装好的一些常用操作
2016/07/28 Javascript
详解JS中的attribute属性
2017/04/25 Javascript
Angualrjs 表单验证的两种方式(失去焦点验证和点击提交验证)
2017/05/09 Javascript
JavaScript反弹动画效果的实现代码
2017/07/13 Javascript
React复制到剪贴板的示例代码
2017/08/22 Javascript
Vue2.0实现组件数据的双向绑定问题
2018/03/06 Javascript
vuejs实现折叠面板展开收缩动画效果
2018/09/06 Javascript
element ui table 增加筛选的方法示例
2018/11/02 Javascript
浅谈vue中关于checkbox数据绑定v-model指令的个人理解
2018/11/14 Javascript
Vue源码解析之数据响应系统的使用
2019/04/24 Javascript
Vue之beforeEach非登录不能访问的实现(代码亲测)
2019/07/18 Javascript
浅谈Vue中render中的h箭头函数
2019/11/07 Javascript
基于JS实现操作成功之后自动跳转页面
2020/09/25 Javascript
[02:42]岂曰无衣,与子同袍!DOTA2致敬每一位守护人
2020/02/17 DOTA
Python开发常用的一些开源Package分享
2015/02/14 Python
python实现复制大量文件功能
2019/08/31 Python
Python3实现建造者模式的示例代码
2020/06/28 Python
Python自动化操作实现图例绘制
2020/07/09 Python
Visual Studio code 配置Python开发环境
2020/09/11 Python
The North Face北面美国官网:美国著名户外品牌
2018/09/15 全球购物
某个公司的Java笔面试题
2016/03/11 面试题
《夜晚的实验》教学反思
2014/02/19 职场文书
小石潭记导游词
2015/02/03 职场文书
土建技术员岗位职责
2015/04/11 职场文书
瞿秋白纪念馆观后感
2015/06/10 职场文书
会计手工模拟做账心得体会
2016/01/22 职场文书
JavaScript实现显示和隐藏图片
2021/04/29 Javascript
python数字图像处理实现图像的形变与缩放
2022/06/28 Python