実装した機能
カレンダーに目覚ましチャレンジが成功した場合、マーキングする。
※2024/01/04の青円の印がマーキング後のイメージです。
使ったもの
カレンダー react-native-calendars
ナビゲーター react-navigation
やったこと
UI
カレンダーの表示 画面の上半分をカレンダー表示にしたかった
デザインはシンプルにデフォルトを利用している。
下半分は別機能に利用するため、残しておきたかった。
const HistoryScreen = () => {
return (
<View style={styles.container}>
{/* 上部:カレンダー */}
<View style={styles.calendarContainer}>
<Calendar
markedDates={markedDates}
// その他のプロパティ
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
calendarContainer: {
// カレンダーコンポーネントのスタイル
},
export default HistoryScreen;
react-native-calendars
テストとして、ダミーデータでマーキングできるか確認してみた
const markedDates = {
"2023-12-01": { selected: true, marked: true, dotColor: "green" }, // 今日
"2023-11-30": { selected: true, marked: true, dotColor: "green" }, // 昨日
};
画面間のデータの受け渡し
次にアラームを止めた際に、historyScreen.jsにデータが流れるようにした
-
App.js でナビゲータを設定
import * as React from "react"; import { View, Text, SafeAreaView } from "react-native"; import { NavigationContainer } from "@react-navigation/native"; import { createStackNavigator } from "@react-navigation/stack"; import HistoryScreen from "./screens/HistoryScreen"; import AlarmScreen from "./screens/AlarmScreen"; const Stack = createStackNavigator(); export default function App() { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="History" component={HistoryScreen} /> <Stack.Screen name="Alarm" component={AlarmScreen} /> </Stack.Navigator> </NavigationContainer> ); }
-
AlarmScreen.jsで引値を設定
// AlarmScreen.js import React, { useState, useEffect } from 'react'; import { View, Text, TouchableOpacity, Switch, StyleSheet, Image, Button } from 'react-native'; import { Audio } from 'expo-av'; import DateTimePicker from '@react-native-community/datetimepicker'; import Modal from 'react-native-modal'; const AlarmScreen = ({ navigation }) => { // ... 他のコード const stopAlarm = async () => { if (sound) { clearInterval(alarmIntervalId); // インターバルの停止 await sound.unloadAsync(); // アラームが止まった情報をHistoryScreenに送信 navigation.navigate('History', { alarmStopped: true }); } }; // ... 他のコード }; export default AlarmScreen;
-
History.jsの更新
routeを引数として、AlarmScreenから渡されたパラメータを利用した。
routeの中身は、以下の通り。{"key": "History-XXXXXXXXXXXXX", "name": "History", "params": {"alarmStopped": true}, "path": undefined}
alarmStoppedをトリガーに、カレンダーにマーキングする処理を実装した。
// HistoryScreen.js import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet, FlatList } from 'react-native'; import { Calendar } from 'react-native-calendars'; const HistoryScreen = ({ route }) => { const [markedDates, setMarkedDates] = useState({}); useEffect(() => { // アラームが止まった情報があればカレンダーを更新 if (route.params?.alarmStopped) { updateCalendar(); // カレンダー更新関数の呼び出し } }, [route.params?.alarmStopped]); const updateCalendar = () => { const currentDate = new Date(); const formattedDate = `${currentDate.getFullYear()}-${currentDate.getMonth() + 1}-${currentDate.getDate()}`; // カレンダーの日付を更新 setMarkedDates((prevMarkedDates) => { return { ...prevMarkedDates, [formattedDate]: { selected: true, marked: true, dotColor: 'green' }, }; }); }; // ... 他のコード }; export default HistoryScreen;
詰まったところ
カレンダーの日付フォーマットがyyyy-mm-dd指定だった。
getMonthで取ると 1月→1 表示になってしまった
そこでpadStart(2, "0")でゼロパディングした。