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

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

程序员文章站 2022-11-25 10:23:30
在原生app开发中,相信很多开发者都会见到这种场景:点击右上角更多的选项,弹出一个更多界面供用户选择。这种控件在原生开发中android可以用popupwindow实现,在...

在原生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',
  },
});

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