PickerView.js 14.7 KB
import React, {Component} from 'react';
import {
    View,
    Text,
    TouchableOpacity,
    TextInput,
    Image
} from 'react-native';
import Picker from 'react-native-picker';

export default class PickerView extends Component {

    constructor(props) {
        super(props);
        this.state = {
            pickerValue: '',
            pickerBegin: '',// 开始时间
            pickerEnd: '',// 结束时间
        };
        this.areaData = {};
        this.attrData = this.props.attrData;
        this.onChangeText = this.props.onChangeText;
        this.onChangeBeginText = this.props.onChangeBeginText;
        this.onChangeEndText = this.props.onChangeEndText;
    }

    componentWillMount() {
        if (this.attrData.type == 'CITY') {
            this.getAreaJsonData()
        }
    }

    /**
     * 获取全国地区数据
     * @returns {Promise<void>}
     */
    async getAreaJsonData() {
        let url = 'http://cdn.xiniunet.com/api/pca.json';
        let data = await fetch(url);
        let json = await data.json();
        this.areaData = json;
    }

    _createDateData() {
        let date = [];
        let year = new Date().getFullYear().toString();
        let yearNumber = parseInt(year)+10;
        for(let i=1970;i<=yearNumber;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;
    }

    _createAreaData() {
        let data = [];
        let len = this.areaData.length;
        for(let i=0;i<len;i++){
            let city = [];
            for(let j=0,cityLen=this.areaData[i]['city'].length;j<cityLen;j++){
                let _city = {};
                _city[this.areaData[i]['city'][j]['name']] = this.areaData[i]['city'][j]['area'];
                city.push(_city);
            }

            let _data = {};
            _data[this.areaData[i]['name']] = city;
            data.push(_data);
        }
        return data;
    }

    _showDatePicker(pickerType) {
        let date = new Date();
        let selectedValue = [
            date.getFullYear()+'年',
            (date.getMonth()+1)+'月',
            date.getDate()+'日',
        ];
        Picker.init({
            pickerConfirmBtnText: '确认',
            pickerCancelBtnText: '取消',
            pickerTitleText: '请选择',
            pickerData: this._createDateData(),
            pickerFontColor: [51, 153 , 255, 1],
            selectedValue: selectedValue,
            onPickerConfirm: (pickedValue, pickedIndex) => {
                let year = pickedValue[0].replace("年", "-");
                let month = pickedValue[1].replace("月", "-");
                let day = pickedValue[2].replace("日", "");
                let dateStr = year + month + day;
                if (pickerType === 'begin') {
                    this.setState({
                        pickerBegin: dateStr
                    })
                } else if (pickerType === 'end') {
                    this.setState({
                        pickerEnd: dateStr
                    })
                } else {
                    this.setState({
                        pickerValue: dateStr
                    })
                }
            },
            onPickerCancel: (pickedValue, pickedIndex) => {
                console.log('date', pickedValue, pickedIndex);
            },
            onPickerSelect: (pickedValue, pickedIndex) => {
                console.log('date', pickedValue, pickedIndex);
            }
        });
        Picker.show();
    }

    _showAreaPicker() {
        Picker.init({
            pickerConfirmBtnText: '确认',
            pickerCancelBtnText: '取消',
            pickerTitleText: '请选择',
            pickerData: this._createAreaData(),
            //selectedValue: ['北京', '北京', '东城区'],
            onPickerConfirm: pickedValue => {
                this.setState({
                    pickerValue: pickedValue
                })
            },
            onPickerCancel: pickedValue => {
            },
            onPickerSelect: pickedValue => {
            }
        });
        Picker.show();
    }

    _showTimePicker() {
        let years = [],
            months = [],
            days = [],
            hours = [],
            minutes = [];

        for(let i=1;i<51;i++){
            years.push(i+1980);
        }
        for(let i=1;i<13;i++){
            months.push(i);
        }
        for(let i=1;i<32;i++){
            days.push(i);
        }
        for(let i=1;i<24;i++){
            hours.push(i);
        }
        for(let i=1;i<61;i++){
            minutes.push(i);
        }
        //let pickerData = [years, months, days, ['am', 'pm'], hours, minutes];
        let pickerData = [years, months, days, hours, minutes];
        let date = new Date();
        let selectedValue = [
            date.getFullYear(),
            date.getMonth()+1,
            date.getDate(),
            //date.getHours(),
            date.getHours(),
            date.getMinutes()
        ];
        Picker.init({
            pickerData,
            selectedValue,
            pickerConfirmBtnText: '确认',
            pickerCancelBtnText: '取消',
            pickerTitleText: '请选择时间',
            wheelFlex: [2, 1, 1, 1, 1],
            onPickerConfirm: pickedValue => {
                this.setState({
                    pickerValue: pickedValue
                })
            },
            onPickerCancel: pickedValue => {
            },
            onPickerSelect: pickedValue => {
                let targetValue = [...pickedValue];
                if(parseInt(targetValue[1]) === 2){
                    if(targetValue[0]%4 === 0 && targetValue[2] > 29){
                        targetValue[2] = 29;
                    }
                    else if(targetValue[0]%4 !== 0 && targetValue[2] > 28){
                        targetValue[2] = 28;
                    }
                }
                else if(targetValue[1] in {4:1, 6:1, 9:1, 11:1} && targetValue[2] > 30){
                    targetValue[2] = 30;

                }
                // forbidden some value such as some 2.29, 4.31, 6.31...
                if(JSON.stringify(targetValue) !== JSON.stringify(pickedValue)){
                    // android will return String all the time,but we put Number into picker at first
                    // so we need to convert them to Number again
                    targetValue.map((v, k) => {
                        if(k !== 3){
                            targetValue[k] = parseInt(v);
                        }
                    });
                    Picker.select(targetValue);
                    pickedValue = targetValue;
                }
            }
        });
        Picker.show();
    }

    _toggle() {
        Picker.toggle();
    }

    _isPickerShow(){
        Picker.isPickerShow(status => {
            alert(status);
        });
    }

    componentWillUnmount() {
        try {
            Picker.hide();
        } catch (e) {

        }
    }

    renderPicker() {
        let {name, code, type, description, isRequired, isPreview} = this.attrData;

        if (type === 'DATE') {
            let extendData = JSON.parse(this.attrData.data);
            let {dateType, dateFormat, placeholder} = extendData;
            let defaultValue = extendData.default;
            return (
                <TouchableOpacity
                    style={{
                        flexDirection: 'row',
                        width: '100%',
                        backgroundColor: 'white',
                        paddingHorizontal: 5,
                        paddingVertical: 10,
                        alignItems: 'center'
                    }}
                    activeOpacity={0.8}
                    onPress={this._showDatePicker.bind(this, "")}
                >
                    <View style={{flex: 1}}>
                        <Text style={{fontSize: 16, color: 'rgba(0, 0, 0, 1)', marginBottom: 5}}>{name||""}</Text>
                        <TextInput
                            style={{width: "100%", backgroundColor: 'white', textAlign: 'left', paddingVertical: 5}}
                            multiline={false}
                            editable={false}
                            onChangeText={text => {
                                if (this.onChangeText) {
                                    this.onChangeText(text)
                                }
                            }}
                            value={this.state.pickerValue}
                            placeholderTextColor={'#999'}
                            placeholder={placeholder}
                            underlineColorAndroid="transparent"
                        />
                    </View>
                    <Image style={{width: 16, height: 16}} source={require('../img/bread.png')} resizeMode={'contain'}/>
                </TouchableOpacity>
            )
        } else if (type === 'PERIOD') {
            let {dateType, dateFormat, beginPlaceholder, endPlaceholder, seperator, isAutoCalculate} = JSON.parse(this.attrData.data);
            return (
                <View>
                    <TouchableOpacity
                        style={{
                            flexDirection: 'row',
                            width: '100%',
                            backgroundColor: 'white',
                            paddingHorizontal: 5,
                            paddingVertical: 10,
                            alignItems: 'center'
                        }}
                        activeOpacity={0.8}
                        onPress={this._showDatePicker.bind(this, 'begin')}
                    >
                        <View style={{flex: 1}}>
                            <Text style={{fontSize: 16, color: 'rgba(0, 0, 0, 1)', marginBottom: 5}}>{"开始时间"}</Text>
                            <TextInput
                                style={{width: "100%", backgroundColor: 'white', textAlign: 'left', paddingVertical: 5}}
                                multiline={false}
                                editable={false}
                                onChangeText={text => {
                                    if (this.onChangeBeginText) {
                                        this.onChangeBeginText(text)
                                    }
                                }}
                                value={this.state.pickerBegin}
                                placeholderTextColor={'#999'}
                                placeholder={beginPlaceholder}
                                underlineColorAndroid="transparent"
                            />
                        </View>
                        <Image style={{width: 16, height: 16}} source={require('../img/bread.png')} resizeMode={'contain'}/>
                    </TouchableOpacity>
                    <View style={{width: '100%', height: 1, backgroundColor: 'rgba(245, 245, 245, 1)'}}/>
                    <TouchableOpacity
                        style={{
                            flexDirection: 'row',
                            width: '100%',
                            backgroundColor: 'white',
                            paddingHorizontal: 5,
                            paddingVertical: 10,
                            alignItems: 'center'
                        }}
                        activeOpacity={0.8}
                        onPress={this._showDatePicker.bind(this, 'end')}
                    >
                        <View style={{flex: 1}}>
                            <Text style={{fontSize: 16, color: 'rgba(0, 0, 0, 1)', marginBottom: 5}}>{"结束时间"}</Text>
                            <TextInput
                                style={{width: "100%", backgroundColor: 'white', textAlign: 'left', paddingVertical: 5}}
                                multiline={false}
                                editable={false}
                                onChangeText={text => {
                                    if (this.onChangeEndText) {
                                        this.onChangeEndText(text)
                                    }
                                }}
                                value={this.state.pickerEnd}
                                placeholderTextColor={'#999'}
                                placeholder={endPlaceholder}
                                underlineColorAndroid="transparent"
                            />
                        </View>
                        <Image style={{width: 16, height: 16}} source={require('../img/bread.png')} resizeMode={'contain'}/>
                    </TouchableOpacity>
                </View>
            )
        } else if (type === 'CITY') {
            let extendData = JSON.parse(this.attrData.data)
            let {enableMultiple, // 启用多选
                enableFilter, // 启用筛选
                placeholder,
            } = extendData;

            let defaultValue = extendData.default;

            return (
                <View style={{width: '100%', backgroundColor: 'white', paddingHorizontal: 5, paddingVertical: 10, flexDirection: 'row', alignItems: 'center'}}>
                    <Text style={{fontSize: 16, color: 'rgba(0, 0, 0, 1)'}}>省市区</Text>
                    <Text style={{
                            fontSize: 16,
                            color: 'rgba(0, 0, 0, 1)',
                            flex: 1,
                            marginLeft: 30,
                            marginRight: 10,
                            textAlign: 'left',
                        }}>{this.state.pickerValue}</Text>
                    <Text style={{fontSize: 16, color: global.homeColor}} onPress={this._showAreaPicker.bind(this)}>选择</Text>
                </View>
            )
        }
    }

    render() {
        return(
            <View style={{width: '100%', backgroundColor: 'white', paddingHorizontal: 5, paddingVertical: 10}}>
                {this.renderPicker()}
            </View>
        );
    }
}