スクロールの挙動がおかしかったバグを修正

This commit is contained in:
harukin-expo-dev-env 2025-04-14 18:52:21 +00:00
parent 99ba90f324
commit fa758c144f
3 changed files with 91 additions and 37 deletions

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef } from "react"; import React, { useEffect, useRef,useState } from "react";
import { createStackNavigator } from "@react-navigation/stack"; import { createStackNavigator } from "@react-navigation/stack";
import { useWindowDimensions, Platform } from "react-native"; import { useWindowDimensions, Platform } from "react-native";
import Constants from "expo-constants"; import Constants from "expo-constants";
@ -50,16 +50,20 @@ export function MenuPage() {
}, []); }, []);
const scrollRef = useRef(null); const scrollRef = useRef(null);
const MapHeight = const [mapHeight,setMapHeight] = useState(0);
height - useEffect(()=>{
tabBarHeight + const MapHeight =
(Platform.OS == "android" ? Constants.statusBarHeight : 0) - height -
100 - tabBarHeight +
((((width / 100) * 80) / 20) * 9 + 10 + 30); (Platform.OS == "android" ? Constants.statusBarHeight : 0) -
100 -
((((width / 100) * 80) / 20) * 9 + 10 + 30);
setMapHeight(MapHeight);
}, [height, tabBarHeight, width]);
useEffect(() => { useEffect(() => {
const unsubscribe = addListener("tabPress", (e) => { const unsubscribe = addListener("tabPress", (e) => {
scrollRef.current.scrollTo({ scrollRef.current.scrollTo({
y: MapHeight - 80, y: mapHeight - 80,
animated: true, animated: true,
}); });
AS.getItem("favoriteStation") AS.getItem("favoriteStation")
@ -73,7 +77,7 @@ export function MenuPage() {
}); });
return unsubscribe; return unsubscribe;
}, [navigation]); }, [navigation, mapHeight]);
return ( return (
<Stack.Navigator> <Stack.Navigator>
<Stack.Screen <Stack.Screen
@ -83,9 +87,7 @@ export function MenuPage() {
gestureEnabled: true, gestureEnabled: true,
headerTransparent: true, headerTransparent: true,
}} }}
children={() => ( children={() => <Menu scrollRef={scrollRef} mapHeight={mapHeight} />}
<Menu scrollRef={scrollRef} />
)}
/> />
<Stack.Screen name="news" options={optionData} component={News} /> <Stack.Screen name="news" options={optionData} component={News} />
<Stack.Screen <Stack.Screen

View File

@ -1,4 +1,4 @@
import React, { useRef } from "react"; import React, { useEffect, useRef } from "react";
import { View, TouchableOpacity, Text, LayoutAnimation } from "react-native"; import { View, TouchableOpacity, Text, LayoutAnimation } from "react-native";
import Ionicons from "react-native-vector-icons/Ionicons"; import Ionicons from "react-native-vector-icons/Ionicons";
@ -44,16 +44,6 @@ export const CarouselTypeChanger = ({
onPress={() => { onPress={() => {
if (!position) return; if (!position) return;
returnToDefaultMode(); returnToDefaultMode();
const { latitude, longitude } = position.coords;
mapsRef.current.animateToRegion(
{
latitude,
longitude,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
},
1000
);
setStationListMode("position"); setStationListMode("position");
}} }}
> >
@ -83,7 +73,7 @@ export const CarouselTypeChanger = ({
marginHorizontal: 5, marginHorizontal: 5,
borderRadius: 50, borderRadius: 50,
}} }}
onPress={() => returnToDefaultMode()} onPressIn={() => returnToDefaultMode()}
> >
<Ionicons <Ionicons
name="menu" name="menu"

88
menu.js
View File

@ -1,5 +1,11 @@
import React, { useRef, useState, useEffect } from "react"; import React, { useRef, useState, useEffect } from "react";
import { Platform, View, ScrollView, useWindowDimensions, LayoutAnimation } from "react-native"; import {
Platform,
View,
ScrollView,
useWindowDimensions,
LayoutAnimation,
} from "react-native";
import Constants from "expo-constants"; import Constants from "expo-constants";
import { import {
configureReanimatedLogger, configureReanimatedLogger,
@ -27,7 +33,7 @@ configureReanimatedLogger({
level: ReanimatedLogLevel.error, // Set the log level to error level: ReanimatedLogLevel.error, // Set the log level to error
strict: true, // Reanimated runs in strict mode by default strict: true, // Reanimated runs in strict mode by default
}); });
export default function Menu({ scrollRef }) { export default function Menu({ scrollRef, mapHeight }) {
const { navigate, addListener, isFocused } = useNavigation(); const { navigate, addListener, isFocused } = useNavigation();
const { favoriteStation } = useFavoriteStation(); const { favoriteStation } = useFavoriteStation();
const { originalStationList } = useStationList(); const { originalStationList } = useStationList();
@ -45,18 +51,42 @@ export default function Menu({ scrollRef }) {
(Platform.OS == "android" ? Constants.statusBarHeight : 0) - (Platform.OS == "android" ? Constants.statusBarHeight : 0) -
100 - 100 -
((((width / 100) * 80) / 20) * 9 + 10 + 30); ((((width / 100) * 80) / 20) * 9 + 10 + 30);
const MapFullHeight = height - tabBarHeight + (Platform.OS == "android" ? Constants.statusBarHeight : 0) - 100; const MapFullHeight =
height -
tabBarHeight +
(Platform.OS == "android" ? Constants.statusBarHeight : 0) -
100;
const returnToTop = (bool = true) => {
scrollRef.current.scrollTo({
y: mapHeight > 80 ?mapHeight - 80 :0,
animated: bool,
});
};
const goToMap = () => {
scrollRef.current.scrollTo({
y: 0,
animated: true,
});
};
useEffect(() => { useEffect(() => {
setTimeout(() => { setTimeout(()=>{
if (scrollRef.current) { returnToTop(false);
scrollRef.current.scrollTo({
y: MapHeight - 80,
animated: false,
});
}
}, 10); }, 10);
}, []); }, [mapHeight]);
const returnToDefaultMode = () => {
LayoutAnimation.configureNext({
duration: 300,
create: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.opacity,
},
update: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.opacity,
},
});
setMapMode(false);
};
//現在地基準の駅名標リストアップ機能 //現在地基準の駅名標リストアップ機能
const { position, locationStatus } = useUserPosition(); const { position, locationStatus } = useUserPosition();
useEffect(() => { useEffect(() => {
@ -125,6 +155,7 @@ export default function Menu({ scrollRef }) {
} }
if (listUpStation[listIndex] == undefined) { if (listUpStation[listIndex] == undefined) {
const count = listIndex - 1; const count = listIndex - 1;
setMapMode(false);
setListIndex(count); setListIndex(count);
} }
}, [listIndex, nearPositionStation, listUpStation]); }, [listIndex, nearPositionStation, listUpStation]);
@ -139,8 +170,10 @@ export default function Menu({ scrollRef }) {
latitudeDelta: 0.05, latitudeDelta: 0.05,
longitudeDelta: 0.05, longitudeDelta: 0.05,
}; };
if (mapMode) return;
mapsRef.current.animateToRegion(mapRegion, 1000); mapsRef.current.animateToRegion(mapRegion, 1000);
}, [listIndex, nearPositionStation, listUpStation, mapsRef]); }, [listIndex, nearPositionStation, listUpStation, mapsRef]);
return ( return (
<View <View
style={{ style={{
@ -157,6 +190,7 @@ export default function Menu({ scrollRef }) {
snapToEnd={false} snapToEnd={false}
decelerationRate={"normal"} decelerationRate={"normal"}
snapToOffsets={[MapHeight - 80]} snapToOffsets={[MapHeight - 80]}
onScrollBeginDrag={() => returnToDefaultMode()}
> >
<MapView <MapView
ref={mapsRef} ref={mapsRef}
@ -186,6 +220,7 @@ export default function Menu({ scrollRef }) {
}, },
}); });
setMapMode(true); setMapMode(true);
goToMap();
}} }}
> >
{listUpStation.map(([{ lat, lng, StationNumber }], index) => ( {listUpStation.map(([{ lat, lng, StationNumber }], index) => (
@ -196,6 +231,33 @@ export default function Menu({ scrollRef }) {
longitude: parseFloat(lng), longitude: parseFloat(lng),
}} }}
image={require("@/assets/reccha-small.png")} image={require("@/assets/reccha-small.png")}
onPress={() => {
setMapMode(false);
setListIndex(index);
if (mapsRef.current) {
mapsRef.current.animateToRegion(
{
latitude: parseFloat(lat),
longitude: parseFloat(lng),
latitudeDelta: 0.05,
longitudeDelta: 0.05,
},
1000
);
}
LayoutAnimation.configureNext({
duration: 300,
create: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.opacity,
},
update: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.opacity,
},
});
returnToTop();
}}
/> />
))} ))}
</MapView> </MapView>
@ -238,4 +300,4 @@ export default function Menu({ scrollRef }) {
</ScrollView> </ScrollView>
</View> </View>
); );
} }