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

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 { useWindowDimensions, Platform } from "react-native";
import Constants from "expo-constants";
@ -50,16 +50,20 @@ export function MenuPage() {
}, []);
const scrollRef = useRef(null);
const [mapHeight,setMapHeight] = useState(0);
useEffect(()=>{
const MapHeight =
height -
tabBarHeight +
(Platform.OS == "android" ? Constants.statusBarHeight : 0) -
100 -
((((width / 100) * 80) / 20) * 9 + 10 + 30);
setMapHeight(MapHeight);
}, [height, tabBarHeight, width]);
useEffect(() => {
const unsubscribe = addListener("tabPress", (e) => {
scrollRef.current.scrollTo({
y: MapHeight - 80,
y: mapHeight - 80,
animated: true,
});
AS.getItem("favoriteStation")
@ -73,7 +77,7 @@ export function MenuPage() {
});
return unsubscribe;
}, [navigation]);
}, [navigation, mapHeight]);
return (
<Stack.Navigator>
<Stack.Screen
@ -83,9 +87,7 @@ export function MenuPage() {
gestureEnabled: true,
headerTransparent: true,
}}
children={() => (
<Menu scrollRef={scrollRef} />
)}
children={() => <Menu scrollRef={scrollRef} mapHeight={mapHeight} />}
/>
<Stack.Screen name="news" options={optionData} component={News} />
<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 Ionicons from "react-native-vector-icons/Ionicons";
@ -44,16 +44,6 @@ export const CarouselTypeChanger = ({
onPress={() => {
if (!position) return;
returnToDefaultMode();
const { latitude, longitude } = position.coords;
mapsRef.current.animateToRegion(
{
latitude,
longitude,
latitudeDelta: 0.05,
longitudeDelta: 0.05,
},
1000
);
setStationListMode("position");
}}
>
@ -83,7 +73,7 @@ export const CarouselTypeChanger = ({
marginHorizontal: 5,
borderRadius: 50,
}}
onPress={() => returnToDefaultMode()}
onPressIn={() => returnToDefaultMode()}
>
<Ionicons
name="menu"

84
menu.js
View File

@ -1,5 +1,11 @@
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 {
configureReanimatedLogger,
@ -27,7 +33,7 @@ configureReanimatedLogger({
level: ReanimatedLogLevel.error, // Set the log level to error
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 { favoriteStation } = useFavoriteStation();
const { originalStationList } = useStationList();
@ -45,18 +51,42 @@ export default function Menu({ scrollRef }) {
(Platform.OS == "android" ? Constants.statusBarHeight : 0) -
100 -
((((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(() => {
setTimeout(()=>{
if (scrollRef.current) {
scrollRef.current.scrollTo({
y: MapHeight - 80,
animated: false,
});
}
returnToTop(false);
}, 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();
useEffect(() => {
@ -125,6 +155,7 @@ export default function Menu({ scrollRef }) {
}
if (listUpStation[listIndex] == undefined) {
const count = listIndex - 1;
setMapMode(false);
setListIndex(count);
}
}, [listIndex, nearPositionStation, listUpStation]);
@ -139,8 +170,10 @@ export default function Menu({ scrollRef }) {
latitudeDelta: 0.05,
longitudeDelta: 0.05,
};
if (mapMode) return;
mapsRef.current.animateToRegion(mapRegion, 1000);
}, [listIndex, nearPositionStation, listUpStation, mapsRef]);
return (
<View
style={{
@ -157,6 +190,7 @@ export default function Menu({ scrollRef }) {
snapToEnd={false}
decelerationRate={"normal"}
snapToOffsets={[MapHeight - 80]}
onScrollBeginDrag={() => returnToDefaultMode()}
>
<MapView
ref={mapsRef}
@ -186,6 +220,7 @@ export default function Menu({ scrollRef }) {
},
});
setMapMode(true);
goToMap();
}}
>
{listUpStation.map(([{ lat, lng, StationNumber }], index) => (
@ -196,6 +231,33 @@ export default function Menu({ scrollRef }) {
longitude: parseFloat(lng),
}}
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>