React Native学习之日期时间

日期、时间选择器:

  • Android 采用api的形式实现
  • iOS 采用组件的形式实现

DatePickerAndroid与TimePickerAndroid

DatePickerAndroid

打开一个标准的Android日期选择器的对话框

static open(options: Object)

可选的options对象的key值如下:

  • date (Date对象或毫秒时间戳) - 默认显示的日期
  • minDate (Date对象或毫秒时间戳) - 可选的最小日期
  • maxDate (Date对象或毫秒时间戳) - 可选的最大日期

在用户选好日期后返回一个Promise,回调参数为一个对象,其中包含有action, year, month (0-11), day。如果用户取消了对话框,Promise仍然会执行,返回的action为DatePickerAndroid.dismissedAction,其他几项参数则为undefined。所以请在使用其他值之前务必先检查action的值。

注意:当Android手机操作系统低于5.0时,设置最小和最大日期会导致api异常,最好不要设置,而是在用户选择完成后再进行检查;api中的open函数打开的界面是系统的界面,不能设置其任何显示样式,如何手机显示不同是因为系统被厂商深度定制。

TimePickerAndroid

打开一个标准的Android时间选择器的对话框

static open(options: Object)

可选的options对象的key值如下:

  • hour (0-23) - 要显示的小时,默认为当前时间
  • minute (0-59) - 要显示的分钟,默认为当前时间
  • is24Hour (boolean) - 如果设为true,则选择器会使用24小时制;如果设为false,则会额外显示AM/PM的选项;如果不设定,则采取当前地区的默认设置

在用户选好时间后返回一个Promise,回调参数为一个对象,其中包含有action, hour (0-23), minute (0-59)。如果用户取消了对话框,Promise仍然会执行,返回的action为TimePickerAndroid.dismissedAction,其他几项参数则为undefined。所以请在使用其他值之前务必先检查action的值。一般用TimePickerAndroid.timeSetAction的取反来判断

注意:is24Hour在某些手机上不会产生作用,用户没有选择时间是因为按下了返回键或取消键;同样的api中的Open打开的是系统的界面。

实现

index.android.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    Navigator,
    ScrollView,
    Image,
    AsyncStorage,
    TouchableOpacity,
    View,
    Platform,
    BackAndroid,
    ToastAndroid,
} from 'react-native';

import DatePicker from './DatePicker.js';
import TimePicker from './TimePicker.js';

class RNAPP extends Component {
    render() {
        let defaultName = 'Home';
        let defaultComponent = Home;
        return (
            <Navigator
                initialRoute = {{ name: defaultName, component: defaultComponent }}
                ref = "navigator"
                //配置场景
                configureScene = {
                    (route) => {
                        //这个是页面之间跳转时候的动画,具体有哪些?可以看这个目录下,有源代码的: node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js
                        return Navigator.SceneConfigs.VerticalDownSwipeJump;
                    }
                }
                renderScene = {
                    (route, navigator) => {
                        let Component = route.component;
                        return <Component {...route.params} navigator={navigator} />
                    }
                }
            />
        );
    }

    componentWillMount() {
        if (Platform.OS === 'android') {
            BackAndroid.addEventListener('hardwareBackPress', this.onBackAndroid);
            //BackAndroid.addEventListener('hardwareBackPress', this.onBackAndroid, true);
        }
    }

    componentWillUnmount() {
        if (Platform.OS === 'android') {
            BackAndroid.removeEventListener('hardwareBackPress', this.onBackAndroid);
        }
    }

    onBackAndroid = () => {
        const navigator = this.refs.navigator;
        const routers = navigator.getCurrentRoutes();
        console.log('当前路由长度:' + routers.length);
        if (routers.length > 1) {
            navigator.pop();
            return true; //接管默认行为
        } else {
            if (this.lastBackPressed && this.lastBackPressed + 2000 >= Date.now()) {
                //最近2秒内按过back键,可以退出应用。
                return false;
            }
            this.lastBackPressed = Date.now();
            ToastAndroid.show('再按一次退出应用', ToastAndroid.SHORT);
            return true;
        }
        return false; //默认行为
    };
}

class Home extends Component {
    render() {
        return (
            <View style={styles.container}>
                <View style={{marginTop: 10}}>
                    <Text onPress={this.goDatePicker.bind(this) } style={styles.btn}>日期选择</Text>
                    <Text onPress={this.goTimePicker.bind(this) } style={styles.btn}>时间选择</Text>
                </View>
                <View style={styles.container} ></View>
                <Text style={styles.author}>Powered by RNAPP.CC</Text>
            </View>
        );
    }

    goDatePicker() {
        const { navigator } = this.props;
        if (navigator) {
            navigator.push({
                name: 'DatePicker',
                component: DatePicker,
            })
        }
    }

    goTimePicker() {
        const { navigator } = this.props;
        if (navigator) {
            navigator.push({
                name: 'TimePicker',
                component: TimePicker,
            })
        }
    }
}

const styles = StyleSheet.create({
    btn: {
        justifyContent: 'flex-start',
        backgroundColor: '#FF7200',
        height: 33,
        textAlign: 'center',
        textAlignVertical: 'center',
        color: '#fff',
        marginLeft: 10,
        marginRight: 10,
        lineHeight: 24,
        marginTop: 20,
        fontSize: 18,
    },
    author: {
        justifyContent: 'flex-end',
        alignItems: 'center',
        marginBottom: 10,
        textAlign: 'center',
    },
    container: {
        flex: 1,
    },
});

AppRegistry.registerComponent('RNAPP', () => RNAPP);

DatePicker.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */

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

export default class DatePicker extends Component {
    constructor(props) {
        super(props);
        this.state = {
            result: 'default',
        };
    }

    componentWillMount() {
        let self = this;
        let today = new Date();
        let theMinDate = new Date(2015, 1, 1);
        let theMaxDate = new Date(2025, 1, 1);
        let option = {
            date: today,
            minDate: theMinDate,
            maxDate: theMaxDate,
        };

        DatePickerAndroid.open(option).then(
            result => {
                if (result.action === DatePickerAndroid.dismissedAction) {
                    self.setState({
                        result: '用户没有选择日期',
                    });
                } else {
                    self.setState({
                        result: '用户选择:' + result.year + '年' + (result.month + 1) + '月' + result.day + '日',
                    });
                }
            }
        ).catch(
            error => {
                console.log('错误:' + error);
            }
        );
    }

    render() {
        return (
            <View style={styles.flex}>
                <View style={[styles.flex, styles.center]}>
                    <Text style={{ fontSize: 18, color: 'red' }}>{this.state.result}</Text>
                </View>
                <Text style={styles.author}>Powered by RNAPP.CC</Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    flex: {
        flex: 1,
    },
    center: {
        justifyContent: 'center',
        alignItems: 'center',
    },
    author: {
        justifyContent: 'flex-end',
        alignItems: 'center',
        marginBottom: 10,
        textAlign: 'center',
    },
});

TimePicker.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */

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

export default class TimePicker extends Component {
    constructor(props) {
        super(props);
        this.state = {
            result: 'default',
        };
    }

    componentWillMount() {
        let self = this;
        let theHour = 18;
        let theMinute = 55;
        let is24Hour = false;
        let option = {
            //hour: theHour,
            //minute: theMinute,
            is24Hour: is24Hour,
        };

        TimePickerAndroid.open(option).then(
            result => {
                if (result.action !== TimePickerAndroid.timeSetAction) {
                    self.setState({
                        result: '用户没有选择时间',
                    });
                } else {
                    self.setState({
                        result: '用户选择:' + result.hour + '小时' + result.minute + '分钟',
                    });
                }
            }
        ).catch(
            error => {
                self.setState({
                    result: '错误:' + error,
                });
            }
        );
    }

    render() {
        return (
            <View style={styles.flex}>
                <View style={[styles.flex, styles.center]}>
                    <Text style={{ fontSize: 18, color: 'red' }}>{this.state.result}</Text>
                </View>
                <Text style={styles.author}>Powered by RNAPP.CC</Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    flex: {
        flex: 1,
    },
    center: {
        justifyContent: 'center',
        alignItems: 'center',
    },
    author: {
        justifyContent: 'flex-end',
        alignItems: 'center',
        marginBottom: 10,
        textAlign: 'center',
    },
});

IOS日期时间组件DatePickerIOS

日期时间选择器在iOS中是以组件的形式存在,DatePickerIOS支持View组件的所有属性,可以设置其宽度、高度、位置等。

这是一个受约束的(Controlled)组件,所以必须监听onDateChange回调函数并且及时更新date属性来使得组件更新,否则用户的修改会立刻被撤销来确保当前显示值和props.date一致。

除了View组件的属性,DatePickerIOS组件还支持如下属性:

  • `date:当前被选中的日期和时间,Date类型
  • maximumDate
  • minimumDate
  • minuteInterval (1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30):用来设置可选的最小分钟单位
  • mode ('date', 'time', 'datetime'):选择器模式
  • timeZoneOffsetInMinutes:以分钟为单位的时区时间差。默认情况下,选择器会选择设备的默认时区。通过此参数,可以指定一个时区。举个例子,要使用北京时间(东八区),可以传递8 * 60。

DatePickerIOS组件的回调方法:

  • onDateChange:当用户修改日期或时间时调用此回调函数。唯一的参数是一个Date对象,表示新的日期和时间(也就是用户选择的)

注意:必须要把一个日期类型的状态机变量赋值给DatePickerIOS组件的date属性,并且在用户操作DatePickerIOS组件修改后,用onDateChange回调的新的date去更新对应的状态机变量,否则会出现用户使用DatePickerIOS组件修改改了时间,几秒钟后,DatePickerIOS组件又回到了原来的时间的情况。

警告的解决方案:

  • warning:Invalid prop 'date' of type 'Number'
  • warning:Required prop 'onDateChange' was not specified

这是一个bug,升级React Native 到0.28及以上版本即可,如果不想升级,可以照这个修改:

修改文件:node_modules/react-native/Libraries/Components/DatePicker/DatePickerIOS.ios.js

参考:https://github.com/facebook/react-native/commit/cec913e7ce05d26181ab4d46e2e41d72acdfb87d
参考:http://stackoverflow.com/questions/35764088/prop-issues-with-datepickerios-in-react-native

范例:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

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

class RNAPP extends Component {
    constructor(props){
    super(props);
        this.state={
            date1: new Date(),
            date2: new Date(),
            date3: new Date(),
        };
    }

    //const timeZoneOffsetInHours = (-1)*(new Date()).getTimezoneOffset()/60;

    onDateChange1(date){
        this.setState({
            date1:date,
        });
    }

    onDateChange2(date){
        this.setState({
            date2:date,
        });
    }

    onDateChange3(date){
        this.setState({
            date3:date,
        });
    }

    render() {
        return (
            <View style={styles.container}>
                <DatePickerIOS style={styles.flex} date={this.state.date1} mode="datetime" onDateChange={date=>this.onDateChange1(date)} />
                <DatePickerIOS style={styles.flex} date={this.state.date2} mode="time" onDateChange={date=>this.onDateChange2(date)} />
                <DatePickerIOS style={styles.flex} date={this.state.date3} mode="date" onDateChange={date=>this.onDateChange3(date)} />
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    flex:{
        flex:1,
    },
    item:{
        marginTop:10,
        marginLeft:5,
        marginRight:5,
        height:30,
        borderWidth:1,
        padding:6,
        borderColor:'#ddd',
    }
});

AppRegistry.registerComponent('RNAPP', () => RNAPP);

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/02/25/react-native-learning-date-and-time/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
React Native学习之日期时间
日期、时间选择器: Android 采用api的形式实现 iOS 采用组件的形式实现 DatePickerAndroid与TimePickerAndroid DatePickerAndroid 打开一个标准的Android……
<<上一篇
下一篇>>
文章目录
关闭
目 录