基于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;
};