本篇主要介绍: 

1. 自定义组件 

2. Alert 对话框

自定义对话框

之前的我都是利用React Native提供的基础组件对它们进行排列组合, 其实自定义也很简单, 我们还是拿​​上一篇文章​​的例子进行扩展。

当我们点击注册的时候,可以弹出一个对话框,让用户确认一下,如下图:

接下来就来试试, 

首先在项目目录下创建​​ConfirmDialog.js​​ 

代码如下:

import React, { Component } from 'react';
import {
StyleSheet,
Text,  // RN提供的组件
View,
BackAndroid
} from 'react-native';
import LoadMoreFooter from "./LoadMoreFooter";
let Dimensions = require('Dimensions');
let totalWidth = Dimensions.get('window').width;//宽
let totalHeight = Dimensions.get('window').height;//高
// 直接导出组件,不用写 module.exports=ConfirmDialog;了
export default class ConfirmDialog extends Component {
constructor(props) {
super(props);
}
render() {
alert('sasas');
// onPress事件直接与父组件传递进来的属性挂接
//numberOfLines 可显示3行
// {'\r\n'}确 定 回车换行后跟着确定,为了克服Text组件不能垂直居中显示
if(1){
return (
<View style={styles.confirmCont}>
<View style={styles.dialogStyle}>
<Text style={styles.textPrompt}>
{this.props.promptToUser}
</Text>
<Text style={styles.cancelButton}
onPress={this.props.userCanceled}
numberOfLines={3}>
{'\r\n'}取 消  2222
</Text>
</View>
</View>
);
}
else {
return (
<View style={styles.confirmCont}>
<View style={styles.dialogStyle}>
<Text style={styles.textPrompt}>
{this.props.promptToUser}
</Text>
<Text style={styles.yesButton}
onPress={this.props.userConfirmed}
numberOfLines={3}>
{'\r\n'}确 定 111
</Text>
</View>
</View>
);
}
}
}
const styles = StyleSheet.create({
confirmCont: {  //全屏显示 半透明 可以看到之前的控件但是不能操作了
position:'absolute',  //声明绝对定位
top:0,
width:totalWidth,
height:totalHeight,
backgroundColor:'rgba(52,52,52,0.5)'  //rgba  a0-1  其余都是十进制数
},
dialogStyle: {
position:'absolute',
left:totalWidth/10, // 定义Dilaog起点位置
top:totalHeight*0.4,
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.12,
backgroundColor:'grey',
fontSize:20,
color:'white',
textAlign:'center'
},
cancelButton: {
position:'absolute',
bottom:10,
right:10,
width:totalWidth*0.35,
height:totalHeight*0.12,
backgroundColor:'grey',
fontSize:20,
color:'white',
textAlign:'center'
}
});
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
Image,
Dimensions,
TouchableOpacity,
TextInput,
ScrollView,
Keyboard,
Alert,
InteractionManager,
View
} from 'react-native';
import JPushModule from 'jpush-react-native';
import Main from './../../pages/main';
import Spinner from 'react-native-spinkit';
import { LOGIN_URL } from '../../component/Urls';
import { Login_Url } from '../../component/NewUrls';
import { timeoutPromise } from './../../component/TimeoutRequest';
import  MDG  from './../../component/ConfirmDialog';
var DeviceInfo = require('react-native-device-info');
import * as networkRequest from 'react-native-networkrequest'
var {height, width, scale, fontScale} = Dimensions.get('window');
// const instance = this;
var loading = false
class LoginNew extends Component {
constructor(props) {
super(props);
const {navigator} = this.props;
this.username = '';
this.password = '';
this.state = {
visible: false,
canLogin: true,
};
// load
storage.load({
key: 'userInfo',
id: '1001'
}).then(ret => {
this.username = ret.username;
this.password = ret.password;
this.token = ret.token;
this.userInfo = ret.userInfo;
if (navigator) {
this.props.navigator.replace({
name: 'Main',
params: {
token: DeviceInfo.getUniqueID(),
username: this.username,
password: this.password,
userInfo: this.userInfo,
badge: this.props.navigator.props.initialRoute.badge,
}
})
}
}).catch(err => {
switch (err.name) {
case 'NotFoundError':
// TODO
break;
case 'ExpiredError':
// TODO
break;
}
});
}
componentWillMount() {
}
componentDidMount() {
InteractionManager.runAfterInteractions(() => {
this.setState({renderPlaceholderOnly: false});
});
}
componentWillUnmount() {
this.timeout && clearTimeout(this.timeout);
}
render() {
return (
<View style={{ flexDirection: 'row',
flex:1,
borderBottomColor: 'lightgray',
borderBottomWidth: 1,
marginLeft: 30,
marginRight: 30,
marginTop: 10,
backgroundColor: '#FFFFFF',
shadowColor: '#ccc',
shadowOffset: {width: 1, height: 1},
shadowOpacity: 0.5,
shadowRadius: 1,
//justifyContent: 'center',
alignItems: 'center',
backgroundColor:'yellow'}}>
<MDG  style={  {flex: 1,
backgroundColor:'yellow'}} userConfirmed={this.userConfirmed}
userCanceled={this.userCanceled}
promptToUser={'使用'+this.state.inputedNum+'号码登录?'}/>
</View>
);
}
forgetPassword(navigator) {
//const {navigator} = this.props;
if (navigator) {
navigator.push({
name: 'ForgetPassword',
})
}
}
forgetPassword(navigator) {
if (navigator) {
navigator.push({
name: 'ForgetPassword',
})
}
}
fetchDataWithURl(url,body=null) {
if (!loading) {
loading = true
return timeoutPromise(20000,fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'text/html;charset=utf-8',
},
body: JSON.stringify(body)
}))
.then((response) =>{
if (response.status == '200') {
return  response.json()
}else {
return  response
}
})
.then((responseJson) => {
//Alert.alert('提示',`ceshi 100000`)
loading = false
if (responseJson.status&&responseJson.status != '200') {
Alert.alert('提示',`网络错误,错误原因${responseJson.status}`)
return
}
console.log(responseJson);
this.setState({
visible: false,
canLogin: true,
})
switch (responseJson.resultCode) {
case 0:
// 设置推送别名
JPushModule.setAlias('paike',()=>{},()=>{})
JPushModule.setTags([this.username],()=>{},()=>{})
// 登陆成功以后 储存用户信息
storage.save({
key: 'userInfo',  //注意:请不要在key中使用_下划线符号!
id: '1001',
rawData: {
username: this.username,
password: this.password,
token: DeviceInfo.getUniqueID(),
},
//         如果不指定过期时间,则会使用defaultExpires参数
// 如果设为null,则永不过期
expires: null,
});
const {navigator} = this.props;
if (navigator) {
navigator.replace({
name: 'Main',
params: {
// token: DeviceInfo.getUniqueID(),
username: this.username,
password: this.password,
// userInfo: responseJson.data.list[0],
}
})
}
break;
case 2:
Alert.alert('提示','登陆失败,用户名不存在!')
break;
case 1:
Alert.alert('提示','登陆失败,用户名或密码错误!')
break;
default:
Alert.alert('提示','登陆失败,未知错误!')
}
})
.catch((error) => {
// console.error(error);
this.timeout = setTimeout(
()=>{
loading = false
Alert.alert('提示','请求超时,请重试',[
{text: '确定', onPress: () => {}},
]);
},50)
// this.setState({visible: false});
});
// networkRequest.Post(20000,url,(responseData)=>{
//   loading = false
//   if (responseJson.status&&responseJson.status != '200') {
//     Alert.alert('提示',`网络错误,错误原因${responseJson.status}`)
//     return
//   }
//   console.log(responseJson);
//   this.setState({
//     visible: false,
//     canLogin: true,
//   })
//   switch (responseJson.resultCode) {
//     case 0:
//     // 设置推送别名
//     JPushModule.setAlias('paike',()=>{},()=>{})
//     JPushModule.setTags([this.username],()=>{},()=>{})
//     // 登陆成功以后 储存用户信息
//       storage.save({
//         key: 'userInfo',  //注意:请不要在key中使用_下划线符号!
//         id: '1001',
//         rawData: {
//           username: this.username,
//           password: this.password,
//           token: DeviceInfo.getUniqueID(),
//         },
// //         如果不指定过期时间,则会使用defaultExpires参数
// // 如果设为null,则永不过期
//         expires: null,
//      });
//     const {navigator} = this.props;
//     if (navigator) {
//       navigator.replace({
//             name: 'Main',
//             params: {
//                 // token: DeviceInfo.getUniqueID(),
//                 username: this.username,
//                 password: this.password,
//                 // userInfo: responseJson.data.list[0],
//             }
//         })
//       }
//           break;
//       case 2:
//           Alert.alert('提示','登陆失败,用户名不存在!')
//           break;
//       case 1:
//           Alert.alert('提示','登陆失败,用户名或密码错误!')
//           break;
//       default:
//           Alert.alert('提示','登陆失败,未知错误!')
//     }
// },(timeOut)=>{
//   loading = false
//   // alert(timeOut)
//   Alert.alert('提示',timeOut,[
//     {text: '确定', onPress: () => {}},
//   ]);
// },'POST',body)
}
}
login() {
if (!this.username) {
Alert.alert('提示','请输入用户名');
return;
}
if (!this.password) {
Alert.alert('提示','请输入密码');
return;
}
if (this.state.canLogin) {
const {navigator} = this.props;
//这段代码用于判断是否用输入用户密码来登录
this.setState({
visible: true,
canLogin: false,
})
var token = DeviceInfo.getUniqueID();
var params = `userName/${this.username}/password/${this.password}`
console.log(Login_Url+params);
this.fetchDataWithURl(Login_Url+params);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f5f9ff',
opacity: 1,
},
loginView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
//backgroundColor: '#f5f9ff',
//backgroundColor: 'red',
},
logoView: {
width: width / 1.5,
height: height / 7,
justifyContent: 'center',
alignItems: 'center',
// backgroundColor: 'red',
},
logo: {
marginBottom: height/6.5,
},
inputView: {
flexDirection: 'row',
borderBottomColor: 'lightgray',
borderBottomWidth: 1,
marginLeft: 30,
marginRight: 30,
marginTop: 10,
backgroundColor: '#FFFFFF',
shadowColor: '#ccc',
shadowOffset: {width: 1, height: 1},
shadowOpacity: 0.5,
shadowRadius: 1,
//justifyContent: 'center',
alignItems: 'center',
},
icon: {
width: 20,
height: 20,
justifyContent: 'center',
marginLeft: 10,
},
button: {
width: width/1.2,
alignItems: 'center',
justifyContent: 'center',
height: 41,
marginLeft: 30,
marginRight: 30,
marginTop: 20,
paddingLeft:30,
paddingRight:30,
backgroundColor: '#529EF3',
borderRadius: 3,
},
spinner: {
marginBottom: 50,
position: 'absolute',
top: height / 15,
left: width / 2 - 501,
},
});
module.exports = LoginNew;

Android选项最多支持3个, 多余的直接忽略不会报错, IOS可以支持多个。style:’cancel’ 的选项再最后显示, 该样式对Android无效, Android第一个选项空间比较大。