基于react-native-date-picker的日期选择组件

news/2024/7/15 19:16:17 标签: react native, react.js, javascript

基于react-native-date-picker的日期选择组件

    • 效果示例图
    • 安装依赖
    • 封装组件PickerDateComponent
    • 使用组件
    • device.js

效果示例图

在这里插入图片描述

安装依赖

https://www.npmjs.com/package/react-native-date-picker?activeTab=readme
npm install react-native-date-picker --save

封装组件PickerDateComponent

import React, {forwardRef, useImperativeHandle, useState} from 'react';
import {
  Modal,
  View,
  Text,
  StyleSheet,
  TouchableOpacity,
  Platform,
} from 'react-native';
import {pxToPd} from '../../common/js/device';
//下拉组件
import DatePicker from 'react-native-date-picker';

const PickerDateComponent = forwardRef((props, ref) => {
  const [visible, setVisible] = useState(false);
  const [options, setOptions] = useState({
    date: '', //回显日期
    mode: 'date', //date:年月日;datetime:年月日时分;time:时分
  });
  const [tempValue, setTempValue] = useState('');
  const hide = value => {
    setVisible(false);
    options.success(value);
  };
  const show = params => {
    const date = params.date? params.date: getCurrentTime(params.mode ? params.mode : 'date');
    setOptions({
      mode: params.mode ? params.mode : 'date', //类型
      date: date, //当前日期
      success: params.success,
    });
    setTempValue(date);
    setVisible(true);
  };
  //点击取消
  const cancelHandle = () => {
    hide(options.date);
  };
  //点击确认
  const confirmHandle = () => {
    hide(tempValue);
  };
  //选择日期
  const dateChangeHandle = value => {
    const beijingTime = convertToBeijingTime(options.mode, value);
    setTempValue(beijingTime);
  };

  const convertToBeijingTime = (mode, date) => {
    const beijingDateTime = new Date(date.getTime());
    return isoToCustomFormat(mode, beijingDateTime.toISOString()); // 转换为ISO字符串表示
  };
  const isoToCustomFormat = (mode, isoString) => {
    const date = new Date(isoString);
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    if (mode === 'datetime') {
      const formattedTime = `${year}-${month}-${day} ${hours}:${minutes}:00`;
      return formattedTime;
    } else if (mode === 'time') {
      const formattedTime = `${hours}:${minutes}`;
      return formattedTime;
    } else {
      const formattedTime = `${year}-${month}-${day}`;
      return formattedTime;
    }
  };

  //获取当前时间
  const getCurrentTime = mode => {
    const now = new Date();
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0');
    const day = String(now.getDate()).padStart(2, '0');
    const hours = String(now.getHours()).padStart(2, '0');
    const minutes = String(now.getMinutes()).padStart(2, '0');
    const seconds = String(now.getSeconds()).padStart(2, '0');

    if (mode === 'datetime') {
      const currentTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
      return currentTime;
    } else if (mode === 'time') {
      const currentTime = ` ${hours}:${minutes}`;
      return currentTime;
    } else {
      const currentTime = `${year}-${month}-${day}`;
      return currentTime;
    }
  };

  useImperativeHandle(ref, () => ({
    show,
  }));
  return (
    <>
      <Modal visible={visible} animationType="fade" transparent>
        <View style={styles.pickerWrap}>
          <View style={styles.pickerBlock}>
            <View style={{height: pxToPd(24)}}></View>
            <View style={styles.pickerContent}>
              {/* 头部 */}
              <View style={styles.pickerHeader}>
                <View style={styles.cancelBtn}>
                  <TouchableOpacity onPress={cancelHandle}>
                    <Text style={styles.cancelText}>取消</Text>
                  </TouchableOpacity>
                </View>
                <View style={styles.timeValue}>
                  <Text style={styles.date}>
                    {tempValue ? tempValue : getCurrentTime(options.mode)}
                  </Text>
                </View>
                <View style={styles.confirmBtn}>
                  <TouchableOpacity onPress={confirmHandle}>
                    <Text style={styles.confirmText}>确认</Text>
                  </TouchableOpacity>
                </View>
              </View>
              {/* 内容 */}
              <View style={styles.pickerBody}>
                {tempValue ? (
                  <DatePicker
                    style={styles.pickerStyle}
                    date={new Date(tempValue)}
                    mode={options.mode}
                    onDateChange={text => dateChangeHandle(text)}
                  />
                ) : (
                  <DatePicker
                    style={styles.pickerStyle}
                    date={new Date(getCurrentTime(options.mode))}
                    mode={options.mode}
                    onDateChange={text => dateChangeHandle(text)}
                  />
                )}
              </View>
            </View>
            <View style={{height: pxToPd(24)}}></View>
          </View>
        </View>
      </Modal>
    </>
  );
});
const styles = StyleSheet.create({
  pickerWrap: {
    flex: 1,
    backgroundColor: 'rgba(0, 0, 0, 0.5)',
    position: 'relative',
  },
  pickerBlock: {
    borderColor: '#dcdcdc',
    borderWidth: pxToPd(1),
    borderStyle: 'solid',
    borderBottomWidth: 0,
    borderLeftWidth: 0,
    borderRightWidth: 0,
    width: '100%',
    height: pxToPd(540),
    position: 'absolute',
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: '#fff',
  },
  pickerContent: {
    width: '91.47%',
    marginLeft: '4.265%',
  },
  pickerHeader: {
    width: '100%',
    height: pxToPd(70),
    flexDirection: 'row',
    justifyContent: 'space-between',
    position: 'relative',
  },
  timeValue: {
    width: pxToPd(300),
    position: 'absolute',
    top: pxToPd(20),
    left: '28.13%',
    alignItems: 'center',
  },
  date: {
    color: '#333',
    fontSize: pxToPd(28),
    fontWeight: '400',
  },
  cancelBtn: {
    borderRadius: pxToPd(35),
    width: pxToPd(150),
    height: pxToPd(70),
    backgroundColor: '#f5f5f5',
    overflow: 'hidden',
  },
  cancelText: {
    color: '#666',
    fontSize: pxToPd(34),
    fontWeight: '400',
    width: pxToPd(150),
    height: pxToPd(70),
    lineHeight: pxToPd(70),
    textAlign: 'center',
  },
  confirmBtn: {
    borderRadius: pxToPd(35),
    width: pxToPd(150),
    height: pxToPd(70),
    backgroundColor: '#FF5B23',
    overflow: 'hidden',
  },
  confirmText: {
    color: '#fff',
    fontSize: pxToPd(34),
    fontWeight: '400',
    width: pxToPd(150),
    height: pxToPd(70),
    lineHeight: pxToPd(70),
    textAlign: 'center',
  },
  pickerBody: {
    width: '100%',
    marginTop: pxToPd(12),
  },
  pickerStyle: {
    width: pxToPd(686),
    backgroundColor: 'white',
    borderRadius: 10,
  },
});
export default PickerDateComponent;

使用组件

//日期组件
import PickerDateComponent from '../../componets/PickerDateComponent';
const [queryParams, setQueryParams] = useState({
    brithday: '1994-04-01', //生日
  });
//生日
  const brithdayRef = useRef(null);
  const brithdayHandle = () => {
    console.log('[生日]');
    brithdayRef.current.show({
      mode: 'date', //类型
      date: queryParams.brithday, //当前日期
      success: value => {
        console.log('[生日]', value);
        setQueryParams({
          ...queryParams,
          brithday: value,
        });
      },
    });
  };
<PickerDateComponent ref={brithdayRef} />

device.js

import {Dimensions, StatusBar, Platform} from 'react-native';
//RN中的尺寸单位为dp,设计稿的单位为px

// 获取屏幕尺寸
const windowDimensions = Dimensions.get('window');

//设备宽度,单位pd
const deviceWidthDp = windowDimensions.width;

//设备高度
const windowHeight = windowDimensions.height;

// 获取状态栏高度
const statusBarCurrentHeight =
  Platform.OS === 'android' ? StatusBar.currentHeight : 20;

//设计稿宽度(这里为750px),单位px
const uiWidthPx = 750;

//px转pd(设计稿中的px转RN中的dp)
//计算公式:设计稿元素宽度(px)/设计稿总宽度(px)=元素的宽度(dp)/屏幕的总宽度(dp)
export const pxToPd = uiElePx => {
  return (uiElePx * deviceWidthDp) / uiWidthPx;
};

//状态栏高度
export const statusBarHeight = () => {
  return statusBarCurrentHeight;
};

// 计算应用程序窗口的高度
// 获取导航栏高度(如果有的话) navigationBarHeight = 0; // 设置默认值
export const appWindowHeight = (navigationBarHeight = 0) => {
  return windowHeight - navigationBarHeight;
};


http://www.niftyadmin.cn/n/4944662.html

相关文章

LabVIEW调用DLL传递结构体参数

LabVIEW 中调用动态库接口时&#xff0c;如果是值传递的结构体&#xff0c;可以根据字段拆解为多个参数&#xff1b;如果参数为结构体指针&#xff0c;可用簇&#xff08;Cluster&#xff09;来匹配&#xff0c;其内存连续相当于单字节对齐。 1.值传递 接口定义&#xff1a; …

ISO 21202:2020 智能交通系统 - 部分自动变道系统 (PALS) - 功能/操作要求和测试规程

​ 介绍 一般来说,车辆配备的驾驶辅助系统和自动驾驶系统可减轻驾驶员的负担,有助于安全驾驶。就变道操作而言,有许多驾驶员并不擅长变道,为了辅助这类驾驶员,部分自动变道系统(PALS)可根据驾驶员的要求,在驾驶员的监督下,在禁止非机动车和行人通行、有明显车道标记的…

C++学习一string类

文章目录 一、定义二、string 的赋值和连接三、比较string四、子串五、寻找string中的字符六、删除string中的字符七、替换string中的字符八、在string中插入字符九、转换成C语言式char *字符串十、字符串拷贝十一、字符串流处理总结 一、定义 string 类是模板类&#xff1a; …

【深度学习--RNN 循环神经网络--附LSTM情感文本分类】

deep learning 系列 --RNN 循环神经网络 什么是序列模型 包括了RNN LSTM GRU等网络模型&#xff0c;主要用途是自然语言处理、语音识别等方面&#xff0c;比如生成乐曲&#xff0c;音频转换为文字&#xff0c;文本情感分类&#xff0c;机器翻译等等 标准模型的缺陷 以往的标…

【Spring专题】Spring之Bean生命周期源码解析——阶段四(Bean销毁)(拓展,了解就好)

目录 前言阅读建议 课程内容一、Bean什么时候销毁二、实现自定义的Bean销毁逻辑2.1 实现DisposableBean或者AutoCloseable接口2.2 使用PreDestroy注解2.3 其他方式&#xff08;手动指定销毁方法名字&#xff09; 三、注册销毁Bean过程及方法详解3.1 AbstractBeanFactory#requir…

Eigen线性代数库相关教程

重要说明&#xff1a;本文从网上资料整理而来&#xff0c;仅记录博主学习相关知识点的过程&#xff0c;侵删。 一、参考资料 Eigen官网 Eigen库学习笔记 Eigen 部分功能介绍 eigen 中四元数、欧拉角、旋转矩阵、旋转向量 Eigen中三维位姿表示方式以及相互转换 SLAM本质剖析-E…

Vue安装单文件组件

安装 npm npm 全称为 Node Package Manager&#xff0c;是一个基于Node.js的包管理器&#xff0c;也是整个Node.js社区最流行、支持的第三方模块最多的包管理器。 npm -v由于网络原因 安装 cnpm npm install -g cnpm --registryhttps://registry.npm.taobao.org安装 vue-cli…

Mariadb高可用MHA (四十二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 1.1 概念 1.2 组成 1.3 特点 1.4 工作原理 二、构建MHA 2.1 ssh免密登录 2.2 主从复制 2.3 MHA安装 2.3.1所有节点安装perl环境 2.3..2 node 2.3.…