import { FC, useRef, useState, useCallback } from "react"; import { View, Text, ScrollView, useWindowDimensions } from "react-native"; import { ExGridViewItem } from "./ExGridViewItem"; import Animated, { useAnimatedStyle, useSharedValue, runOnJS, } from "react-native-reanimated"; import { Gesture, GestureDetector } from "react-native-gesture-handler"; export const ExGridView: FC<{ data: { trainNumber: string; array: string; name: string; type: string; time: string; }[]; }> = ({ data }) => { const groupedData = {}; const groupKeys = []; const { width } = useWindowDimensions(); data.forEach((item) => { const hour = item.time.split(":")[0]; if (!groupedData[hour]) { groupedData[hour] = []; groupKeys.push(hour); } groupedData[hour].push(item); }); // ドラッグ位置を保持する共有値 const widthX = useSharedValue(width); const savedWidthX = useSharedValue(width); const [scrollEnabled, setScrollEnabled] = useState(true); const scrollRef = useRef(null); const [contentScrollPos, setContentScrollPos] = useState(0); // ScrollViewの有効/無効を切り替える関数 const toggleScrollEnabled = useCallback((enabled: boolean) => { setScrollEnabled(enabled); }, []); // パンジェスチャー(ドラッグ)のハンドラー const pinchGesture = Gesture.Pinch() .onUpdate((e) => { const calc = savedWidthX.value * e.scale; widthX.value = calc > width ? calc : width; //runOnJS(scrollToRightEnd)(); }) .onEnd(() => { savedWidthX.value = widthX.value; }); const gesture = Gesture.Pan() .minPointers(2) // 最低2本指 .maxPointers(2) // 最大2本指 .onTouchesDown((e) => { if (e.numberOfTouches >= 2) runOnJS(toggleScrollEnabled)(false); }) .onTouchesUp((e) => { runOnJS(toggleScrollEnabled)(true); }) .onEnd((e) => { runOnJS(toggleScrollEnabled)(true); }); // ジェスチャーを組み合わせる const composed = Gesture.Simultaneous(pinchGesture, gesture); // アニメーションスタイル const animatedStyle = useAnimatedStyle(() => ({ width: widthX.value, })); return ( { setContentScrollPos(d.nativeEvent.contentOffset.x); }} onContentSizeChange={(d) => { if (d < contentScrollPos) { scrollRef.current?.scrollToEnd(); } }} ref={scrollRef} contentContainerStyle={{ flexDirection: "column", }} > {Array.from({ length: 60 }, (_, i) => i + 1).map((num) => { if (num % 5 === 0) { return ( {num - 5} ); } else return <>; })} (分) i * 2) : [] } > {groupKeys.map((hour) => [ {hour}時台 , {groupedData[hour].map((d, i) => ( ))} , ])} ); };