您的位置:首页 > Web前端 > React

React Native自定义组件——弹出框

2017-03-22 14:19 423 查看
这里用到的其实是一个新的场景页面 而不是像原生的组件一样 悬浮在页面之上,它实现的原理是从新绘制一个带弹出框样式的页面,除了弹出框之外都是灰色的,且将要显示弹出框页面的布局完全移植过来。

这里通过 BackAndroid API 实现了点击返回键 自定义对话框消失的效果

BackAndroid API 的工作机制是,当挂接多个Listener 后,用户按下返回键时,多个Listener 都会监听到返回键按下事件,并且他们的处理函数都会被执行,执行的顺序是天津的顺序,这些处理函数都执行后,只要有一个处理函数返回了true(表示返回键被按下事件已经被处理),返回键被按下事件就不会交个Android框架处理,也就是说,应用程序没有 办法退出。

程序的入口文件  index.android.js

import React, {Component} from 'react';
import {AppRegistry,Navigator,BackAndroid,Alert} from 'react-native';

import RegisterLeaft from './RegisterLeaft';
import WaitingLeaft  from './WaitingLeaft';

export default class NavigatorModule extends Component {

constructor (props) {
super(props)
this.handleBack = this._handleBack.bind(this) // 返回一个绑定好this的方法并存储于当前实例中
}

configureScene(router){
return Navigator.SceneConfigs.FadeAndroid;
}

renderScene(router,navigator){
switch(router.name) {
case  "register":
return <RegisterLeaft navigator={navigator}/>
case  "waiting" :
return <WaitingLeaft
phoneNumber = {router.phoneNumber}
userPW = {router.userPW}
navigator={navigator}
/>
}
}
componentDidMount() {
BackAndroid.addEventListener("NoviModuleListener",this.handleBack);
}

_handleBack () {
const nav=this.navigator;
if(nav!=null){
const routers=nav.getCurrentRoutes();
if(routers.length>1){
nav.pop();
return true;
}
}
return false;
}

componentWillUnount(){
BackAndroid.removeEventListener("NoviModuleListener",this.handleBack);
}

render(){
return(
<Navigator
ref={nav => {this.navigator=nav}}
initialRoute={{name:'register'}}
configureScene={this.configureScene}
renderScene ={(route,navigator) =>this.renderScene(route,navigator)}
/>
);
}
}

AppRegistry.registerComponent('AwesomeProject', () => NavigatorModule);
对话框组件 ConfirmDialog.js

import React, {Component} from 'react';
import {AppRegistry,View,Text,StyleSheet,BackAndroid,Alert} from 'react-native';

let Dimensions = require('Dimensions');
let totalWidth = Dimensions.get('window').width;
let totalHeight = Dimensions.get('window').height;

export default class ConfirmDialog extends Component{

constructor (props) {
super(props)
this.newHandleBack = this._newHandleBack.bind(this) // 返回一个绑定好this的方法并存储于当前实例中
}
render(){
return(
<View style={styles.ConfirmContent}>
<View style={styles.dialogStyle}>
<Text style={styles.textPrompt}>
{this.props.promptToUser}
</Text>
<Text style={styles.yesButton}
onPress = {()=>{this.props.userConfirmed()}}
>
{'\r\n'}确定
</Text>
<Text style={styles.cancelButton}
onPress = {()=>{this.props.userCanceled()}}
>
{'\r\n'}取消
</Text>
</View>
</View>
);
}

componentDidMount() {
let amIStillAlive = this.props.amIStillAlive;
let navigator =this.props.navigator;
BackAndroid.addEventListener("ConfirmDialogListener",this.newHandleBack);
}
componentWillUnmount(){
BackAndroid.removeEventListener("ConfirmDialogListener",this.newHandleBack);
}

_newHandleBack () {
let amIStillAlive = this.props.amIStillAlive();
let navigator =this.props.navigator;
if(amIStillAlive==true){
this.props.userCanceled();
return true;
}
return false;
}
}

let styles = StyleSheet.create({
ConfirmContent:{
position:"absolute",
top:0,
width:totalWidth,
height:totalHeight,
backgroundColor:'rgba(52,52,52,0.5)'
},
dialogStyle:{
position:"absolute",
top:totalHeight * 0.4,
left:totalWidth / 10,
width:totalWidth * 0.8,
height:totalHeight * 0.3,
backgroundColor:'white'
},
textPrompt:{
position:'absolute',
top:10,
left:10,
fontSize:20,
color:'black'
},
yesButton:{
position:'absolute',
bottom:10,
left:10,
width:totalWidth*0.35,
height:totalHeight*0.1,
backgroundColor:'gray',
fontSize:20,
color:'white',
textAlign:'center'
},
cancelButton:{
position:'absolute',
bottom:10,
right:10,
width:totalWidth*0.35,
height:totalHeight*0.1,
backgroundColor:'gray',
fontSize:20,
color:'white',
textAlign:'center'
}
}
);
注册页面 RegisterLeaft.js 

import React, {Component} from 'react';
import {AppRegistry,StyleSheet, Text, View, TextInput,Alert,Navigator} from 'react-native';

import ConfirmDialog  from './ConfirmDialog';
let Dimensions = require('Dimensions');
let totalWidth = Dimensions.get('window').width;
let leftStartPoint = totalWidth * 0.1;
let componentWidth = totalWidth * 0.8;

export default class RegisterLeaft  extends Component {

constructor(props) {
super(props);
this.state={
inputedNum:"",
inputedPW:"",
needToConfirm:false
};
}

render() {
if(this.state.needToConfirm==true)
return this.renderWithDialog();
return (
<View style = {styles.container} >
<TextInput style = {styles.numberInputStyle}
placeholder = {'请输入手机号:'}
onChangeText={(inputedNum)=>this.setState({inputedNum})}
/>
<Text style = {styles.textPromptStyle} >
您输入的手机号:{this.state.inputedNum}
</Text >
<TextInput style = {styles.passwordInputStyle}
placeholder = { '请输入密码' }
onChangeText={(inputedPW)=>this.setState({inputedPW})}
password = 'true'
/>
<Text style = {styles.bigTextPrompt}
onPress = {()=>{this.userPressConfirm()}}
>
确定
</Text>
</View>);
}

renderWithDialog(){
return (
<View style = {styles.container} >
<TextInput style = {styles.numberInputStyle}
placeholder = {'请输入手机号:'}
onChangeText={(inputedNum)=>this.setState({inputedNum})}
/>
<Text style = {styles.textPromptStyle} >
您输入的手机号:{this.state.inputedNum}
</Text >
<TextInput style = {styles.passwordInputStyle}
placeholder = {'请输入密码'}
onChangeText={(inputedPW)=>this.setState({inputedPW})}
password = 'true'
/>
<Text style = {styles.bigTextPrompt}
onPress ={()=>{this.userPressConfirm()}}
>
确定
</Text>
<ConfirmDialog
userConfirmed={()=>{this.userConfirmed()}}
userCanceled = {()=>{this.userCanceled()}}
amIStillAlive= {()=>{this.tellConfirmDialogItsStatus()}}
promptToUser ={'使用'+this.state.inputedNum+'号码登录?'}
>
</ConfirmDialog>
</View>);
}

userPressConfirm(){
this.setState({needToConfirm:true});

}
userCanceled(){
this.setState({needToConfirm:false});
}
userConfirmed(){
this.setState({needToConfirm:true});
this.props.navigator.push({
phoneNmuber:this.state.inputedNum,
userPW:this.state.inputedPW,
name:"waiting"
});
}

tellConfirmDialogItsStatus(){
return this.state.needToConfirm;
}

}

let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white'
},
numberInputStyle: {
top: 20,
left: leftStartPoint,
width: componentWidth,
backgroundColor: 'gray',
fontSize: 20

},
textPromptStyle: {
top: 30,
left: leftStartPoint,
width: componentWidth,
fontSize: 20
},
passwordInputStyle: {
top: 50,
left: leftStartPoint,
width: componentWidth,
backgroundColor: 'gray',
fontSize: 20
},
bigTextPrompt: {
top: 70,
left: leftStartPoint,
width: componentWidth,
backgroundColor: 'gray',
color: 'white',
textAlign: 'center',
fontSize: 40
}
});
等待页面 WaitingLeaft.js

import React, {Component} from 'react';
import {AppRegistry, StyleSheet, Text, View, TextInput} from 'react-native';

export default class WaitingLeaft extends Component{

render() {
return (
<View style = {styles.container} >
<Text style = {styles.textPromptStyle} >
注册使用手机号码:{this.props.phoneNumber}
</Text >
<Text style = {styles.textPromptStyle} >
注册使用密码:{this.props.userPW}
</Text >
<Text style = {styles.bigTextPrompt}
onPress = {this.goBack.bind(this)}
>
返回
</Text>
</View>);
}

goBack(){
this.props.navigator.push(
{
name:"register"
}
);
}
}

let styles = StyleSheet.create({
container: {
flex: 1,
justifyContent:'center',
alignItems:'center',
backgroundColor:'#F5FCFF'
},
textPromptStyle: {
fontSize: 20

},
bigTextPrompt: {
width: 300,
backgroundColor: 'gray',
color: 'white',
textAlign: 'center',
fontSize: 60
}
});




代码 链接: https://pan.baidu.com/s/1c2EHTD2 密码: hy7b







                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: