在议程日历中仅从上个月和上个月中选择任何日期时,React Native Calendar周视图无法正确呈现

时间:2019-12-23 07:39:52

标签: react-native react-native-calendars

我开始为我的应用程序使用react native日历。我在其中一个屏幕上使用了议程。但是,选择日期时有一个奇怪的问题。我已经设置了pastScrollRange和futureScrollRange。问题是,只要我从日历的第一个月中选择任何日期,就会向我显示下个月的最后一周。例如,如果2017年1月是日历的第一个月,则在选择任何日期后,它将向我显示2017年2月的最后一周。类似地,当我从日历中的最后一个月中选择任何日期时,它将显示该月的第一周。我一直在试图找出解决方案,但似乎无济于事。任何指导将不胜感激。

请查看以下屏幕截图。在下面的屏幕截图中,2017年12月是日历的第一个月,而2021年12月是日历的最后一个月份。

Image1 Image2

这是我的代码。

import React, { useState, useEffect } from "react";
import { View, Text, Image, TouchableOpacity, SafeAreaView, StyleSheet, Platform } from "react-native";
import { Agenda } from "react-native-calendars";
import Toast from "react-native-simple-toast";
import moment from "moment";
import "../../../Utils/Globals";
import { SERVICES_FOR_DATE_URL, CLIENT_ID_KEY } from "../../../Config/Routes";
import { requestData } from "../../../Api/ApiRequests";
import ServiceEvent from "./ServiceEvent";
//import { checkLocationPermission, requestLocationPermission, getDistance } from "../../../Location/LocationManager";
import Geolocation from "react-native-geolocation-service";
import Icon from "react-native-vector-icons/FontAwesome";

let watchId = "";

const ServicesCalendarScreen = (props) => {

    //let date = moment();
    //date = moment().format("MMMM YYYY");
    //date = moment().month() + moment().year();
    //Toast.show(""+date, Toast.LONG);

    //events state hook for selected day events
    const [events, setEvents] = useState(null);

    //set selected month and year
    const [date, setDate] = useState(moment().format("MMMM YYYY"));

    //hook for setting selected date to pass to onRefresh prop of agenda to refresh the selected date contents
    const [dateToRefresh, setDateToRefresh] = useState(moment().format("YYYY-MM-DD"));

    const getSelectedDayEvents = (date) => {

        let serviceDate = moment(date);
        serviceDate = serviceDate.format("DD/MM/YYYY");

        const data = { ClientId : CLIENT_ID, ServiceDate : serviceDate };

        //returned result with fetch api
        requestData(PROVIDER_URL + SERVICES_FOR_DATE_URL, data).then((result) => {
            console.log(result);
            if (result.status == "Successful") {
                if (result.data != "") {
                    //changing the received result object so that calendar can view the event on selected date
                    let modifiedData = { [date] : result.data };
                    setEvents(modifiedData);
                    console.log(modifiedData);
                    //to change the month and year on top of agenda
                    //setDate(moment(date).format("MMMM YYYY"));
                }
                else {
                    let modifiedData = { [date] : result.data };
                    setEvents(modifiedData);
                }
            }
            else {
                Toast.show(result.message ? result.message : result, Toast.SHORT);
            }

        })
        .catch((error) => {
            console.log(error);
        });
    }

    //this condition is implemented when we need to refresh data when we appear from another screen
    if (typeof props.navigation.state.params !== "undefined") {
        const refreshData = props.navigation.state.params.refreshData;
        const selectedDate = props.navigation.state.params.selectedDate;
        props.navigation.state.params = undefined;
        let date = selectedDate.replace(/\//g, "-");
        date = moment(selectedDate, "DD-MM-YYYY").format("YYYY-MM-DD");
        //date = date.format("YYYY-MM-DD");
        getSelectedDayEvents(date);
        // if (refreshData) {
        //     let currentDate = moment();
        //     currentDate = currentDate.format("YYYY-MM-DD");
        //     getSelectedDayEvents(currentDate);
        // }
    }

    //getting the service date to populate the selected day calendar events
    useEffect(() => {

        let currentDate = moment();
        currentDate = currentDate.format("YYYY-MM-DD");
        getSelectedDayEvents(currentDate);

        // if (Platform.OS === "android") {
        //     //checking the status if user has location permission enabled, if not then show the permission popup to user
        //     requestLocationPermission().then((status) => {
        //         console.log(status);
        //         if (status === "granted") {
        //             //getting location response through promise from another file
        //             // const watchID = await getPosition().then((position) => {
        //             //     console.log(position);
        //             // })
        //             // .catch((error) => {
        //             //     console.log(error);
        //             // });
        //             // console.log(watchID);

        //             //options for location
        //             const options = {
        //                 enableHighAccuracy: true, 
        //                 timeout : 15000, 
        //                 interval : 30000
        //             };

        //             //for iOS only
        //             if (Platform.OS === "ios")
        //                 setRNConfiguration(options);

        //             //continuously get location after every 30 seconds
        //             watchID = Geolocation.watchPosition((position) => {
        //                 const currentLat = position.coords.latitude;
        //                 const currentLng = position.coords.longitude;
        //                 const residentLat = -37.901639;
        //                 const residentLng = 145.054707;
        //                 Toast.show("Location Updated", Toast.LONG);
        //                 getDistance(currentLat, currentLng, residentLat, residentLng).then((data) => {
        //                     console.log(data);
        //                 })
        //                 .catch((error) => {
        //                     console.log(error);
        //                 });
        //             },
        //             (error) => {
        //                 console.log(error);
        //             },
        //             options);
        //         }
        //         else {
        //             console.log("No permission allowed for accessing location");
        //         }

        //     })
        //     .catch((error) => {
        //         console.log(error);
        //     });
        // }
        // else {

        // }
    }, []);

    // useEffect(() => {
    //     checkLocationPermission().then((permissionStatus) => {
    //         switch (permissionStatus) {
    //             case "granted":
    //                 break;
    //             case "denied":
    //                 break;
    //             case "blocked":
    //                 break;
    //             case "unavailable":
    //                 break;
    //         }
    //     })
    //     .catch((error) => {
    //         console.log(error);
    //     });
    // });

    return (
        <View style = {{ flex : 1 }}>
            <View style = { styles.dateViewStyle }>
                <TouchableOpacity 
                    style = { styles.dateButtonStyle }
                    //onPress = {() => openCalendar ? setOpenCalendar(false) : setOpenCalendar(true) }
                    >
                    <Text style = { styles.dateStyle }>{ date }</Text>
                </TouchableOpacity>
            </View>
            <Agenda items = { events } /*shouldOpenCalendar = { openCalendar }*/
                // Enable or disable scrolling of calendar list
                scrollEnabled = { false }
                // Max amount of months allowed to scroll to the past. Default = 50
                pastScrollRange = { 12 }
                // Max amount of months allowed to scroll to the future. Default = 50
                futureScrollRange = { 12 }
                // callback that gets called when items for a certain month should be loaded (month became visible)
                // loadItemsForMonth={(month) => {
                //         let currentDate = moment();
                //         currentDate = currentDate.format("YYYY-MM-DD");
                //         if (currentDate == month.dateString) {
                //             getSelectedDayEvents(month.dateString);
                //         }
                //         console.log(currentDate);
                //     }
                // }
                // callback that fires when the calendar is opened or closed
                onCalendarToggled = {(calendarOpened) => calendarOpened ? setDate("") : null }
                // callback that gets called on day press
                onDayPress={(day)=>{
                        getSelectedDayEvents(day.dateString);
                        //to change the month and year on top of agenda
                        setDate(moment(day.dateString).format("MMMM YYYY"));
                        //set the date in case onRefresh is executed
                        setDateToRefresh(day.dateString);
                    }
                }
                // callback that gets called when day changes while scrolling agenda list
                onDayChange={(day)=>{
                        console.log('day changed')
                    }
                }
                // specify how each item should be rendered in agenda
                renderItem={(item, firstItemInDay) => {
                        return (<ServiceEvent eventDetails = { item } navigation = { props.navigation } />);
                    }
                }
                // specify how each date should be rendered. day can be undefined if the item is not first in that day.
                // renderDay={(day, item) => {
                //         return (<View><Text>Text</Text></View>);
                //     }
                // }
                // specify how empty date content with no items should be rendered
                renderEmptyDate = {() => {
                    return (
                        <View style = { styles.viewStyle }>
                            <Icon name = "exclamation-triangle" size = { 30 } color = "#2079B3"/>
                            <Text style = { styles.textStyle }>No services on this date</Text>
                        </View>
                    );
                }}
                // specify how agenda knob should look like
                renderKnob={() => { 
                    return (
                        <TouchableOpacity /*onPress = {() => openCalendar ? setOpenCalendar(false) : setOpenCalendar(true)}*/>
                            <Icon name = "chevron-down" size = { 20 } color = "#2079B3" />
                        </TouchableOpacity>
                    ); 
                }}
                // specify what should be rendered instead of ActivityIndicator
                // renderEmptyData = {() => {
                //     return (<View><Text>No service on this date</Text></View>);
                // }}
                // specify your item comparison function for increased performance
                rowHasChanged={(r1, r2) => {return r1 !== r2;}}

                // By default, agenda dates are marked if they have at least one item, but you can override this if needed
                // markedDates={{
                //     '2019-11-22': {selected: true, marked: true},
                //     '2019-11-23': {marked: true},
                //     '2019-11-24': {disabled: true}
                // }}

                // If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the refreshing prop correctly.
                onRefresh={() => getSelectedDayEvents(dateToRefresh)}

                //styling agenda calendar view
                theme = {{ 
                    textDayFontSize: 16,
                    textMonthFontSize: 20,
                    textDayHeaderFontSize: 16
                }} 

            />
        </View>

    );
}

const styles = StyleSheet.create({
    dateViewStyle : {
        flexDirection : "row",
        justifyContent : "center",
        height : "auto"
    },
    dateStyle : {
        color : "#2079B3",
        fontSize : 18,
        padding : 10,
        margin : 5,
        borderRadius: 5
    },
    viewStyle : {
        flexDirection : "row",
        justifyContent : "center",
        padding : 5,
        marginTop : 30,
        height : 50
    },
    textStyle : {
        fontSize : 18,
        margin : 5
    }
});

export default ServicesCalendarScreen;

2 个答案:

答案 0 :(得分:0)

您可以做两件事:

  • 更新版本“ react-native-calendars”:“ 1.220.0” 修复了日历折叠时标题的怪异滚动行为。

  • 您可以为主题设置样式,就像我分别为iOS和Android处理的情况一样:

distributionUrl=https://privateRepo/gradle-5.0-bin.zip

例如:

'stylesheet.calendar.header': { week: { marginTop: Platform.OS=='ios'?6:2, flexDirection: 'row', justifyContent: 'space-between' } }

我的议程组件供参考:

<Agenda
theme={{
'stylesheet.calendar.header': { week: { marginTop: Platform.OS=='ios'?6:2, flexDirection: 'row', justifyContent: 'space-between' } }
}}>

答案 1 :(得分:0)

我发现这是因为最后一个日历页面仍在堆栈导航中,并且高度没有正确计算。 因此,我从堆栈导航中删除了所有数据(您可以找到完全相同的日历页面并将其删除)。 之后,导航到该页面,一切正常。

import {NavigationActions, StackActions} from 'react-navigation';
const resetAction = StackActions.reset({
      index: 0,
      actions: [NavigationActions.navigate({ routeName: 'name of calendar component' })],
    });
    navigation.dispatch(resetAction)

不需要任何样式上的改变。