项目中需要使用地址选择器和时间选择器,在react-native-picker基础上做了一个封装。
1.react-native-picker安装步骤查看: 安装步骤
2.封装代码:
/**
* Created by justin on 2018/3/19.
*/
import React, { Component } from 'react';
import {
AppRegistry,
Text,
View,
Dimensions,
StyleSheet,
Platform,
BackHandler,
Animated,
Easing
} from 'react-native';
import Picker from 'react-native-picker';
import {deviceInfo} from '../../utils'
import area from '../../asset/area.json';
import PropTypes from 'prop-types';
export default class SelectAddressOrDate extends Component<{}> {
static propTypes = {
cancel:PropTypes.string, //取消按钮
title:PropTypes.string, //中间标题
confirm:PropTypes.string, //确认按钮
callBackAddressValue:PropTypes.func, //地址回调方法
callBackDateValue:PropTypes.func, //时间回调方法
pickerBg:PropTypes.array, //背景颜色
startYear:PropTypes.number, //开始年份
endYear:PropTypes.number, //结束年份
synchronousRefresh:PropTypes.bool, //是否同步刷新
}
static defaultProps = {
cancel:'取消',
title:'请选择',
confirm:'确认',
pickerBg:[255,255,255,1],
startYear:2010,
endYear:2030,
synchronousRefresh:false
}
constructor(props){
super(props);
this.state={
xPosition: new Animated.Value(0),
isShow:false, //弹框是否显示
selectedValue:[] //选择的值 address: ['河北', '唐山', '古冶区'] date: ['2018年', '1月', '1日']
}
}
componentWillMount(){
if (Platform.OS === 'android') {
BackHandler.addEventListener('hardwareBackPress', this.onBackAndroid);
}
}
componentWillUnmount(){
if (Platform.OS === 'android') {
BackHandler.removeEventListener('hardwareBackPress', this.onBackAndroid);
}
}
onBackAndroid = () => {
if(this.state.isShow){
this.hide();
return true;
}
return false
};
/**
* 在外部调用 显示地址
* @param pickedValue ['河北', '唐山', '古冶区']
*/
showAddress(pickedValue){
if(!this.state.isShow){
this.state.selectedValue=pickedValue
this._showAreaPicker()
this.showAnimal()
this.state.isShow=true
}
}
/**
* 在外部调用 显示地址
* @param pickedValue ['2018年', '1月', '1日']
*/
showDate(pickedValue){
if(!this.state.isShow){
this.state.selectedValue=pickedValue
this._showDatePicker()
this.showAnimal()
this.state.isShow=true
}
}
/**
* 隐藏地址
*/
hide(){
if(this.state.isShow){
Picker.hide()
this.hideAnimal()
this.state.isShow=false
}
}
/**
* 地址确认值
* @param pickedValue ['河北', '唐山', '古冶区']
*/
confirmAddressValue(pickedValue){
this.props.callBackAddressValue&&this.props.callBackAddressValue(pickedValue)
}
/**
* 时间确认值
* @param pickedValue ['2018年', '1月', '1日']
*/
confirmDateValue(pickedValue){
this.props.callBackDateValue&&this.props.callBackDateValue(pickedValue)
}
_showAreaPicker() {
Picker.init({
pickerData: this._createAreaData(),
selectedValue:this.state.selectedValue,
onPickerConfirm: pickedValue => {
this.confirmAddressValue(pickedValue)
this.hide()
},
onPickerCancel: pickedValue => {
this.hide()
},
onPickerSelect: pickedValue => {
//Picker.select(['山东', '青岛', '黄岛区'])
if(this.props.synchronousRefresh){
this.confirmAddressValue(pickedValue)
}
},
pickerBg:this.props.pickerBg,
pickerCancelBtnText:this.props.cancel,
pickerConfirmBtnText:this.props.confirm,
pickerTitleText:this.props.title,
...this.props
});
Picker.show();
}
_showDatePicker() {
Picker.init({
pickerData: this._createDateData(),
selectedValue:this.state.selectedValue,
pickerFontColor: [0, 0 ,0, 1],
onPickerConfirm: (pickedValue, pickedIndex) => {
this.confirmDateValue(pickedValue)
this.hide()
},
onPickerCancel: (pickedValue, pickedIndex) => {
this.hide()
},
onPickerSelect: (pickedValue, pickedIndex) => {
if(this.props.synchronousRefresh){
this.confirmDateValue(pickedValue)
}
},
pickerBg:this.props.pickerBg,
pickerCancelBtnText:this.props.cancel,
pickerConfirmBtnText:this.props.confirm,
pickerTitleText:this.props.title,
...this.props
});
Picker.show();
}
_createAreaData() {
let data = [];
let len = area.length;
for(let i=0;i<len;i++){
let city = [];
for(let j=0,cityLen=area[i]['city'].length;j<cityLen;j++){
let _city = {};
_city[area[i]['city'][j]['name']] = area[i]['city'][j]['area'];
city.push(_city);
}
let _data = {};
_data[area[i]['name']] = city;
data.push(_data);
}
return data;
}
_createDateData() {
let date = [];
for(let i=this.props.startYear;i<this.props.endYear;i++){
let month = [];
for(let j = 1;j<13;j++){
let day = [];
if(j === 2){
for(let k=1;k<29;k++){
day.push(k+'日');
}
//Leap day for years that are divisible by 4, such as 2000, 2004
if(i%4 === 0){
day.push(29+'日');
}
}
else if(j in {1:1, 3:1, 5:1, 7:1, 8:1, 10:1, 12:1}){
for(let k=1;k<32;k++){
day.push(k+'日');
}
}
else{
for(let k=1;k<31;k++){
day.push(k+'日');
}
}
let _month = {};
_month[j+'月'] = day;
month.push(_month);
}
let _date = {};
_date[i+'年'] = month;
date.push(_date);
}
return date;
}
showAnimal(){
Animated.timing(
this.state.xPosition,
{
toValue: 1,
easing: Easing.linear,
duration: 300,
}
).start()
}
hideAnimal(){
Animated.timing(
this.state.xPosition,
{
toValue: 0,
easing: Easing.linear,
duration: 200,
}
).start()
}
render(){
return (
<Animated.View
style={[styles.contain,{transform: [{
translateY: this.state.xPosition.interpolate({
inputRange: [0, 1],
outputRange: [ deviceInfo.deviceHeight , 0]
}),
}]
} ]}>
</Animated.View>
)
}
}
const styles = StyleSheet.create({
contain:{
width: deviceInfo.deviceWidth,
height: deviceInfo.deviceHeight,
position: 'absolute',
opacity: 0.3,
backgroundColor: "#666",
left: 0,
bottom: 0,
},
});
3.使用方式:
import React, {Component} from 'react';
import {
AppRegistry,
Text,
FlatList,
StyleSheet,
Dimensions,
View,
TouchableOpacity,
ToastAndroid,
Alert
} from 'react-native';
import SelectAddressOrDate from '../../common/SelectAddressOrDate'
import {deviceInfo} from '../../../utils'
export default class TabView4 extends Component<{}> {
constructor(props){
super(props)
this.state={
address:[],
time:[],
}
}
componentDidMount() {
}
open(){
this.refs.SelectAddressOrDate.showAddress(this.state.address)
}
openTime(){
this.refs.SelectAddressOrDate.showDate(this.state.time)
}
callBackDateValue(value){
this.setState({
time:value
})
}
callBackAddressValue(value){
this.setState({
address:value
})
}
render() {
return (
<View style={styles.contain}>
<View style={styles.select}>
<TouchableOpacity onPress={()=>this.open()}>
<Text>{this.state.address[0]}{this.state.address[1]}{this.state.address[2]}</Text>
<Text>打开地址</Text>
</TouchableOpacity>
</View>
<View style={styles.select}>
<TouchableOpacity onPress={()=>this.openTime()}>
<Text>{this.state.time[0]}{this.state.time[1]}{this.state.time[2]}</Text>
<Text>选择时间</Text>
</TouchableOpacity>
</View>
<SelectAddressOrDate ref={'SelectAddressOrDate'} callBackAddressValue={this.callBackAddressValue.bind(this)} callBackDateValue={this.callBackDateValue.bind(this)}/>
</View>
)
}
}
const styles = StyleSheet.create({
contain: {
flex: 1,
backgroundColor: '#f4f4f4',
alignItems: 'center',
},
select:{
width:deviceInfo.deviceWidth,
height:60,
alignItems:'center',
justifyContent:'center',
marginTop:30
}
});
4:传送门