web-dev-qa-db-fra.com

À l'aide de react-native-community / datetimepicker, comment puis-je afficher un sélecteur de date / heure sur Android?

Pour iOS, la bibliothèque react-native-community/datetimepicker prend en charge le mode datetime, dans lequel il affiche un sélecteur de date et d'heure.

Cependant, ce mode n'est PAS disponible pour Android.

Y a-t-il une solution pour afficher 2 sélecteurs consécutifs, un pour la date et un autre pour l'heure?

class ShiftTimingScreen extends Component {

    state = {
        dateTimePickerVisible: false, 
        dateOrTimeValue: new Date(), 
    };

    render() {
        return (
            <View>
                <TouchableOpacity
                    onPress={() => this.setState({ dateTimePickerVisible: true, })}
                >
                    <Input
                        label='Shift Starts At'
                        placeholder={"01/01/2019 - 09:00 AM"}
                        editable={false}
                        value={this.state.dateOrTimeValue.toLocaleDateString()}
                    />
                </TouchableOpacity>

                {this.state.dateTimePickerVisible &&
                    (<DateTimePicker
                        mode={"datetime"} // THIS DOES NOT WORK ON Android. IT DISPLAYS ONLY A DATE PICKER.
                        display='default' // Android Only  
                        is24Hour={false} // Android Only 
                        value={defaultShiftStartDateTime}

                        onChange={(event, value) => {
                            this.setState({
                                dateOrTimeValue: value,
                                dateTimePickerVisible: Platform.OS === 'ios' ? true : false,
                            });

                            if (event.type === "set")
                                console.log("value:" , value);
                        }}
                    />)}
            </View>
        );
    } 
} 

export default ShiftTimingScreen;
2
Bilal Abdeen

Veuillez trouver ci-dessous une solution de contournement pour cette limitation.

import React, { Component } from 'react';
import { TouchableOpacity, View } from 'react-native';
import { Input } from 'react-native-elements';

import DateTimePicker from '@react-native-community/datetimepicker';
import XDate from 'xdate'; 

class ShiftTimingScreen extends Component {
    state = {
        // The values, which we get from each of the DateTimePickers. 
        // These values can be saved into your app's state. 
        StartingDateTimeValue: null,
        ToDateValue: null,
        ToTimeValue: null,

        // for iOS & Android: When this flag is true, the relevant <DateTimePicker> is displayed
        isStartingDateTimePickerVisible: false,
        isToDatePickerVisible: false,
        isToTimePickerVisible: false,

        // The value of the <DateTimePicker> is stored in this variable, which is used to pass data between the date & time pickers 
        dateOrTimeValue: null, 

        // ONLY FOR Android: note that the current version of the <DateTimePicker> does NOT support "datetime" mode on Android.
        // So, I am using the following 2 flags (datePickerVisible & timePickerVisible) to provide this functionality.

        // (1) ONLY FOR Android: When the datePickerVisible flag is true, the <DateTimePicker> is displayed in "date" mode
        datePickerVisible: false, 

        // (2) ONLY FOR Android: When the timePickerVisible flag is true, the <DateTimePicker> is displayed in "time" mode
        timePickerVisible: false,
    };


    saveStartingDateTime = (value) => { 
        console.log("saveStartingDateTime - value:", value); 
        this.setState({
            StartingDateTimeValue: value,
        });
    }; 

    saveEndingDate = (value) => { 
        console.log("saveEndingDate - value:", value);
        this.setState({
            ToDateValue: value,
        });
    }; 

    saveEndingTime = (value) => {
        console.log("saveEndingTime - value:", value);
        this.setState({
            ToTimeValue: value,
        });
    };

    fRenderDateTimePicker = (dateTimePickerVisible, visibilityVariableName, dateTimePickerMode, defaultValue, saveValueFunctionName ) => {
        // dateTimePickerVisible:   a flag, which is used to show/hide this DateTimePicker
        // visibilityVariableName:              the name of the state variable, which controls showing/hiding this DateTimePicker. 
            // The name of the variable is received in (visibilityVariableName), and the value of it is received in the argument (dateTimePickerVisible).
        // dateTimePickerMode:      the mode mode of this DateTimePicker
        // defaultValue:                the default value, which should be selected initially when the DatTimePicker is displayed 
        // saveValueFunctionName:   the function, which would be called after the user selects a value. 
            // In my case it is a Redux's action creator, which saves the selected value in the app's state. 

        return (
            <View>
                {/* A. For iOS, display the picker in "date", "time" or "datetime" mode - No need for any customisation */}
                {Platform.OS === 'ios' && dateTimePickerVisible &&
                    (<DateTimePicker
                        mode={dateTimePickerMode}
                        value={defaultValue}

                        onChange={ (event, value) => {
                            this.setState({
                                dateOrTimeValue: value,

                                // We are done. Hide the <DatTimePicker>
                                // Technically speaking, since this part of the script is only relevant to a certain platform, I don't need to check for the platform (below). 
                                // Note that [visibilityVariableName] refers to the NAME of a state variable
                                [visibilityVariableName]: Platform.OS === 'ios' ? true : false,
                            });

                            if (event.type === "set") {
                                saveValueFunctionName(value);
                                // console.log("visibilityVariableName:", [visibilityVariableName], " - value:", value); 
                            }

                        }}
                    />)}

                {/* B.1 For Android - "date" mode:      display the picker in "date" mode */}
                {/*       For Android - "datetime" mode: display the picker in "date" mode (to be followed by another picker (below) in "time" mode) */}
                {Platform.OS === 'Android' && dateTimePickerVisible && this.state.datePickerVisible &&
                    (<DateTimePicker
                        mode={"date"}
                        display='default' // 'default', 'spinner', 'calendar', 'clock' // Android Only 
                        value={defaultValue}

                        onChange={ (event, value) => {
                            this.setState({
                                // In case of (mode == datetime), the TIME part will be added to "dateOrTimeValue" using another DateTimePicker (below).
                                dateOrTimeValue: value,
                                datePickerVisible: false,
                            });

                            // When the mode is "datetime" & this picker was set (the user clicked on OK, rather than cancel), 
                            // we need to display another DateTimePicker in TIME mode (below) 
                            if (event.type === "set" && dateTimePickerMode === "datetime") {
                                this.setState({
                                    timePickerVisible: true,
                                });
                            }

                            // When the mode is "date" & this picker was set (the user clicked on OK, rather than cancel), 
                            // (1) We need to hide this picker. 
                            // (2) Save the data. Otherwise, do nothing. Date will be saved after the TIME picker is launched (below). 
                            else if (event.type === "set" && dateTimePickerMode === "date") {
                                // console.log("saveValueFunctionName: ", saveValueFunctionName); 
                                this.setState({ 
                                    [visibilityVariableName]: Platform.OS === 'ios' ? true : false, 
                                }); 

                                saveValueFunctionName(value);
                                // console.log("visibilityVariableName:", [visibilityVariableName], " - value:", value); 
                            }

                        }}
                    />)}

                {/* B.2 For Android - "time" mode:      display the picker in "time" mode */}
                {/*       For Android - "datetime" mode: display the picker in "time" mode (following another picker (above) in "date" mode) */}
                {Platform.OS === 'Android' && dateTimePickerVisible && this.state.timePickerVisible &&
                    (<DateTimePicker
                        mode={"time"}
                        display='spinner' // 'default', 'spinner', 'calendar', 'clock' // Android Only 
                        is24Hour={false} // Android Only 
                        value={defaultValue}

                        onChange={(event, value) => {
                            // 1. In case of (mode == "time"), (value) is assigned to (newDateTime), which will be used below (as is with no additions)
                            let newDateTime = value;

                            // 2. In case of (mode == "datetime"), 
                            if (event.type === "set" && dateTimePickerMode === "datetime") {

                                // 2.1. Get the (date) part from the previously displayed DATE picker, which saved its value into (this.state.dateValue)
                                newDateTime = this.state.dateOrTimeValue;

                                // 2.2. Get the (hours & minutes) parts from this TIME Picker, which saved its value into (value) 
                                const newHours = value.getHours();
                                const newMinutes = value.getMinutes();

                                // 2.3 Combine 2.1 & 2.2 (above) into (newDateTime).
                                newDateTime.setHours(newHours);
                                newDateTime.setMinutes(newMinutes);
                                newDateTime.setSeconds(0);
                            }

                            this.setState({
                                dateOrTimeValue: newDateTime,
                                datePickerVisible: false,
                                timePickerVisible: false,

                                // We are done. Hide the <DatTimePicker>
                                // Technically speaking, since this part of the script is only relevant to a certain platform, I don't need to check for the platform (below). 
                                [visibilityVariableName]: Platform.OS === 'ios' ? true : false,
                            });

                            if (event.type === "set") {
                                saveValueFunctionName(newDateTime);
                                // console.log("visibilityVariableName:", [visibilityVariableName], " - newDateTime:", newDateTime); 
                            } 
                        }}

                    />)} 
            </View>
        );      
    }; 

    // This function formats date values. Obviously, using it is optional. 
    // If you decide to use it, remember that it needs the XDate library: 
    // import XDate from 'xdate';
    fFormatDateTime = (date1, format1 = "datetime") => {
        // date1:   the date to be formatted 
        // format1: the date mode - "datetime" , "date" OR "time"
        if (date1 === null) {
            return null;
        }

        // else:
        const format2 = format1.toLowerCase();
        let dateFormatted;
        const date2 = new XDate(date1);

        switch (format2) {
            case "datetime": {
                dateFormatted = date2.toString('dd/MM/yyyy - hh:mm TT');
                return dateFormatted;
            }
            case "date": {
                dateFormatted = date2.toString('dd/MM/yyyy');
                return dateFormatted;
            }
            case "time": {
                dateFormatted = date2.toString('hh:mm TT');
                return dateFormatted;
            }
            default:
                return null;
        } 
    };

    // This function shows/hides the initial DateTimePicker 
    // If the mode is "datetime", another picker will be displayed by the DATE picker 
    fRenderDatePicker = (mode, visibilityVariableName) => {
        // mode:                        specifies the mode of the <DateTimePicker> 
        // visibilityVariableName:  the name of the state variable, which controls showing/hiding this DateTimePicker. 
        switch (mode) {
            case "datetime":
                return this.setState({ [visibilityVariableName]: true, datePickerVisible: true, timePickerVisible: false });
            case "date":
                return this.setState({ [visibilityVariableName]: true, datePickerVisible: true, timePickerVisible: false });
            case "time":
                return this.setState({ [visibilityVariableName]: true, datePickerVisible: false, timePickerVisible: true });
        }
    }

    render() {
        // 1. For the "Shift Start", Initial/Default value for the DateTimePicker 
        // // defaultShiftStartDateTime: (tomorrow's date at 9 AM)
        let defaultShiftStartDateTime = new Date();
        defaultShiftStartDateTime.setDate(defaultShiftStartDateTime.getDate() + 1);
        defaultShiftStartDateTime.setHours(9);
        defaultShiftStartDateTime.setMinutes(0);
        defaultShiftStartDateTime.setSeconds(0);

        // 2. For the "Shift End", Initial/Default value for the DateTimePicker 
        let defaultShiftEndDateTime = new Date();
        defaultShiftEndDateTime.setDate(defaultShiftEndDateTime.getDate() + 1);
        defaultShiftEndDateTime.setHours(17);
        defaultShiftEndDateTime.setMinutes(0);
        defaultShiftEndDateTime.setSeconds(0);

        return (
                <View>
                    <TouchableOpacity
                        // THE FOLLOWING ARGUMENT VALUE IS THE (1st place OF 2) PLACES, WHICH DIFFERENTIATE BETWEEN THE DIFFERENT MODES (DATETIME, DATE & TIME)
                        onPress={() => {
                            // this.setState({ isStartingDateTimePickerVisible: true, });
                            this.fRenderDatePicker("datetime", "isStartingDateTimePickerVisible");
                        }}>
                        <Input
                            label='Starting Date & Time'
                            placeholder={"01/01/2019 - 09:00 AM"}
                            editable={false}
                            value={this.fFormatDateTime(this.state.StartingDateTimeValue)}
                        />
                    </TouchableOpacity>

                    {// This function would render the necessary DateTimePicker only if the relevant state variable is set (above)
                    this.fRenderDateTimePicker(
                        this.state.isStartingDateTimePickerVisible,
                        "isStartingDateTimePickerVisible",

                        // THE FOLLOWING ARGUMENT VALUE IS THE (2nd place OF 2) PLACES, WHICH DIFFERENTIATE BETWEEN THE DIFFERENT MODES (DATETIME, DATE & TIME)
                        "datetime",

                        defaultShiftStartDateTime,

                        // This is my function, which saves the selected value to my app's state. 
                        // YOU NEED TO REPLACE IT WITH SOMETHING RELEVANT TO YOUR APP. 
                        this.saveStartingDateTime,
                    )}


                    <TouchableOpacity
                        onPress={() => {
                            // this.setState({ isToDatePickerVisible: true, });
                            this.fRenderDatePicker("date", "isToDatePickerVisible");
                        }}>
                        <Input
                            label='Ending Date'
                            placeholder={"01/01/2019"}
                            editable={false}
                            value={this.fFormatDateTime(this.state.ToDateValue, "date")}
                        />
                    </TouchableOpacity>
                    {this.fRenderDateTimePicker(
                        this.state.isToDatePickerVisible,
                        "isToDatePickerVisible",
                        "date",
                        defaultShiftEndDateTime,

                        // This is my function, which saves the selected value to my app's state. 
                        // YOU NEED TO REPLACE IT WITH SOMETHING RELEVANT TO YOUR APP. 
                        this.saveEndingDate,
                    )}

                    <TouchableOpacity
                        onPress={() => {
                            // this.setState({ isToTimePickerVisible: true, });
                            this.fRenderDatePicker("time", "isToTimePickerVisible");
                        }}>
                        <Input
                            label='Ending Time'
                            placeholder={"09:00 AM"}
                            editable={false}
                            value={this.fFormatDateTime(this.state.ToTimeValue, "time")}
                        />
                    </TouchableOpacity>
                    {this.fRenderDateTimePicker(
                        this.state.isToTimePickerVisible,
                        "isToTimePickerVisible",
                        "time",
                        defaultShiftEndDateTime,

                        // This is my function, which saves the selected value to my app's state. 
                        // YOU NEED TO REPLACE IT WITH SOMETHING RELEVANT TO YOUR APP. 
                        this.saveEndingTime,
                    )}
                </View>
        );
    } // end of: render()
} // end of: component

export default ShiftTimingScreen;

3
Bilal Abdeen

J'ai utilisé le code ci-dessous pour effectuer la sélection de la date et de l'heure à l'aide du react-native-community/datetimepicker paquet. J'espère que c'est utile.

const [date, setDate] = useState(
  props.item.time ? new Date(props.item.time) : new Date() // to set default from props or current date
);
const [time, setTime] = useState(
  props.item.time ? new Date(props.item.time) : new Date() // to set default from props or current date
);
const [mode, setMode] = useState('date');
const [show, setShow] = useState(false);

const onChange = (event, selectedValue) => {
  setShow(Platform.OS === 'ios');
  if (mode == 'date') {
    const currentDate = selectedValue || new Date();
    setDate(currentDate);
    setMode('time');
    setShow(Platform.OS !== 'ios'); // to show time
  } else {
    const selectedTime = selectedValue || new Date();
    setTime(selectedTime);
    setShow(Platform.OS === 'ios'); // to hide back the picker
    setMode('date'); // defaulting to date for next open
  }
};
const showMode = currentMode => {
  setShow(true);
  setMode(currentMode);
};

const showDatePicker = () => {
  showMode('date');
};
return 
  (<View>
  <TouchableOpacity onPress={showDatePicker}>
    <Text style={styles.title}>{formatDate(date, time)}</Text>
  </TouchableOpacity>
  {show && (
    <DateTimePicker
      value={date}
      minimumDate={Date.parse(new Date())}
      display='default'
      mode={mode}
      onChange={onChange}
    />
  )}
  </View>);


const formatDate = (date, time) => {
return `${date.getDate()}/${date.getMonth() +
  1}/${date.getFullYear()} ${time.getHours()}:${time.getMinutes()}`;
};
0
parkourkarthik