react native 自己动手写日历区间选择控件
2018-06-04 本文已影响126人
tomorrow_chen
首先还是看效果图:
image.png代码复制直接可用
import React, { Component } from 'react'
import { StyleSheet, View, ScrollView, TouchableOpacity, Text, Dimensions } from 'react-native'
import moment from 'moment'
const width = Dimensions.get('window').width
const now = new Date()
export default class App extends Component {
constructor(props) {
super(props)
this.state = {
nowDate: new Date(),
showBtn: true,
startDate: new Date(),
count: 0,
endDate: new Date() + 48 * 60 * 60 * 1000
}
}
_onPressButton(date) {
let { count } = this.state
let temp = ++count
if (this.props.range) { // 区间选择
this.setState({
count: temp
})
if (temp % 2 === 1) { // 第一个日期
this.setState({
startDate: date,
endDate: date,
showBtn: false
})
} else { // 第二个日期
if (+new Date(this.state.startDate) >= +new Date(date)) { // 第一个日期大于等于第二个日期
this.setState({
startDate: date,
endDate: date,
count: ++temp,
showBtn: false
})
return
}
this.setState({
endDate: date,
showBtn: true
})
}
return
}
// 单日点击
this.setState({
nowDate: date
}, () => {
this.callBack()
})
}
callBack() {
// 回调事件
}
render() {
let { nowDate, showBtn, startDate, endDate } = this.state
let content = []
for (let i = 0; i < this.props.monthNum; i++) { // 月数循环
let date = new Date(now.getFullYear(), now.getMonth() + i, 1);
let week = date.getDay(); // 当月从星期几开始
let days = new Date(now.getFullYear(), now.getMonth() + i + 1, 0).getDate(); // 当月的天数
let dayList = [];
for (let y = 0; y < week; y++) { // 前面补空占位
dayList.push(
<View style={styles.day}>
<Text style={styles.dayText}></Text>
</View>
)
}
for (let x = 1; x <= days; x++) { // 循环天数
let toDay = new Date(now.getFullYear(), now.getMonth() + i, x); // 今天
let g = this.props.goliday[moment(toDay).format('YYYY-MM-DD')];
if (!g) { // 节假日
g = x;
}
let node = <View style={styles.day}><TouchableOpacity onPress={this._onPressButton.bind(this, toDay)} activeOpacity={0.5}><Text style={[styles.dayText, { color: '#000' }]}>{g}</Text></TouchableOpacity></View>
if (i == 0 && x < now.getDate()) { // 今天以前的日期置灰 ,无事件
if ((week + x) % 7 == 1 || (week + x) % 7 == 0) { // 周末 蓝色
node = <View style={styles.day}><Text style={[styles.dayText, { color: '#105eae' }]}>{g}</Text></View>
} else {
node = <View style={styles.day}><Text style={[styles.dayText, { color: '#999' }]}>{g}</Text></View>
}
} else if (i == 0 && x == now.getDate()) { // 今天
node = <View style={styles.day}><TouchableOpacity onPress={this._onPressButton.bind(this, toDay)} activeOpacity={0.5}><Text style={[styles.dayText, { color: '#000' }]}>今天</Text></TouchableOpacity></View>
} else if ((week + x) % 7 == 1 || (week + x) % 7 == 0) { // 周末 蓝色
node = <View style={styles.day}><TouchableOpacity onPress={this._onPressButton.bind(this, toDay)} activeOpacity={0.5}><Text style={[styles.dayText, { color: '#105eae' }]}>{g}</Text></TouchableOpacity></View>
}
if (!this.props.range) { // 单日
if (moment(toDay).format('YYYY-MM-DD') === moment(nowDate).format('YYYY-MM-DD')) { // 选中日期
node = <View style={[styles.day, styles.curr]}><TouchableOpacity onPress={this._onPressButton.bind(this, toDay)} activeOpacity={0.5}><Text style={[styles.dayText, { color: '#fff' }]}>{g}</Text></TouchableOpacity></View>
}
} else { // 区间
if (+new Date(toDay) > +new Date(startDate) && +new Date(toDay) < +new Date(endDate)) {
node = <View style={[styles.day, styles.range]}><TouchableOpacity onPress={this._onPressButton.bind(this, toDay)} activeOpacity={0.5}><Text style={[styles.dayText, { color: '#fff' }]}>{g}</Text></TouchableOpacity></View>
}
if (moment(toDay).format('YYYY-MM-DD') === moment(endDate).format('YYYY-MM-DD')) { // 选中日期
node = <View style={[styles.day, styles.curr]}><TouchableOpacity onPress={this._onPressButton.bind(this, toDay)} activeOpacity={0.5}><Text style={[styles.startdayText, { color: '#fff', paddingTop: ((width / 7) - 20) * 0.2, paddingBottom: ((width / 7) - 20) * 0.1 }]}>{g}</Text><Text style={[styles.start, { paddingTop: ((width / 7) - 20) * 0.1, paddingBottom: ((width / 7) - 20) * 0.2 }]}>离店</Text></TouchableOpacity></View>
}
if (moment(toDay).format('YYYY-MM-DD') === moment(startDate).format('YYYY-MM-DD')) { // 选中日期
node = <View style={[styles.day, styles.curr]}><TouchableOpacity onPress={this._onPressButton.bind(this, toDay)} activeOpacity={0.5}><Text style={[styles.startdayText, { color: '#fff', paddingTop: ((width / 7) - 20) * 0.2, paddingBottom: ((width / 7) - 20) * 0.1 }]}>{g}</Text><Text style={[styles.start, { paddingTop: ((width / 7) - 20) * 0.1, paddingBottom: ((width / 7) - 20) * 0.2 }]}>入住</Text></TouchableOpacity></View>
}
}
dayList.push(node)
}
content.push( // 添加节点
<View>
<View style={styles.head}><Text>{moment(date).format('YYYY年MM月')}</Text></View>
<View style={styles.content}>
{dayList}
</View>
</View>
)
}
return (
<View style={styles.container}>
<View style={styles.weekContainer}>
<Text style={[styles.weekText]}>日</Text>
<Text style={styles.weekText}>一</Text>
<Text style={styles.weekText}>二</Text>
<Text style={styles.weekText}>三</Text>
<Text style={styles.weekText}>四</Text>
<Text style={styles.weekText}>五</Text>
<Text style={[styles.weekText]}>六</Text>
</View>
<ScrollView
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false} // 隐藏垂直指示器
>
{content}
</ScrollView>
{
showBtn ?
<TouchableOpacity onPress={this.callBack.bind(this)} style={styles.btn}><Text style={{ color: '#fff' }}>确定</Text></TouchableOpacity> : null
}
</View>
)
}
}
const styles = StyleSheet.create({
container: {
paddingTop: 20,
flex: 1,
backgroundColor: '#fff'
},
weekContainer: {
width: width,
height: 35,
backgroundColor: '#105eae',
flexDirection: 'row',
alignItems: 'center'
},
weekText: {
width: width / 7,
lineHeight: 35,
textAlign: 'center',
color: '#fff'
},
content: {
flexDirection: 'row',
alignItems: 'center',
flexWrap: 'wrap'
},
day: {
width: width / 7 - 0.1,
},
dayText: {
textAlign: 'center',
fontSize: 16,
paddingVertical: ((width / 7) - 20) * 0.5
},
startdayText: {
textAlign: 'center',
fontSize: 14
},
curr: {
backgroundColor: '#105eae',
},
range: {
backgroundColor: '#6CAFF5'
},
head: {
alignItems: 'center',
margin: 10
},
start: {
color: '#fff',
textAlign: 'center',
fontSize: 14
},
btn: {
width: width,
height: 45,
backgroundColor: '#105eae',
alignItems: 'center',
alignSelf: 'center',
justifyContent: 'center'
}
})
App.defaultProps = {
monthNum: 6, // 显示的月数
range: true,
goliday: { // 节假日在这里添加
'2018-04-05': '清明',
'2018-05-01': '劳动',
'2018-06-18': '端午',
'2018-09-24': '中秋',
'2018-10-01': '国庆'
}
}