视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
react native仿微信PopupWindow效果的实例代码
2020-11-27 22:33:14 责编:小采
文档


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

实现思路分析:

要实现上面的视图,有很多种实现方式。前面的文章说过,要实现弹框相关的可以用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" ?  : 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//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 ?  : 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',
 },
});

下载本文
显示全文
专题