jrshikoku/components/DynamicHeaderScrollView.js
2025-01-28 13:47:46 +00:00

183 lines
4.4 KiB
JavaScript

import { ScrollView, View, Animated, LayoutAnimation } from "react-native";
import React, { useEffect, useMemo, useState, useLayoutEffect } from "react";
import { NativeViewGestureHandler } from "react-native-gesture-handler";
import { AS } from "../storageControl";
export const DynamicHeaderScrollView = (props) => {
const {
children,
actionSheetRef = {},
containerProps = {},
shortHeader = <></>,
longHeader = <></>,
topStickyContent,
styles,
from,
scrollHandlers,
} = props;
const [headerSize, setHeaderSize] = useState("default");
useLayoutEffect(() => {
AS.getItem("headerSize")
.then((res) => {
if (res) setHeaderSize(res);
})
.catch((e) => {
AS.setItem("headerSize", "default");
});
}, []);
useEffect(() => {
switch (headerSize) {
case "small":
setHeaderVisible(true);
return;
case "big":
case "default":
default:
setHeaderVisible(false);
break;
}
}, [headerSize]);
const viewHeader = useMemo(() => {
switch (from) {
case "AllTrainIDList":
case "NearTrainDiagramView":
case "LED2":
return true;
default:
return false;
}
}, [from]);
const Max_Header_Height = headerSize == "small" ? 0 : viewHeader ? 0 : 200;
const Min_Header_Height = viewHeader ? 0 : 80;
const Scroll_Distance = Max_Header_Height - Min_Header_Height;
const shotHeaderStyle = {
on: {
height: Min_Header_Height,
backgroundColor: "#0099CC",
margin: 0,
top: 0,
opacity: 1,
},
off: {
height: Max_Header_Height,
backgroundColor: "#0099CC",
margin: 0,
top: 0,
opacity: 0,
},
};
const longHeaderStyle = {
on: {
height: Max_Header_Height,
backgroundColor: "#0099CC",
margin: 0,
top: 0,
opacity: 1,
},
off: {
height: 0,
backgroundColor: "#0099CC",
margin: 0,
top: 0,
opacity: 0,
},
};
const StickyStyle = {
on: {
position: "absolute",
width: "100%",
flex: 1,
top: Max_Header_Height,
zIndex: 1,
},
off: {
position: "absolute",
width: "100%",
flex: 1,
top: Min_Header_Height,
zIndex: 1,
},
};
const [headerVisible, setHeaderVisible] = useState(false);
const onScroll = (event) => {
scrollHandlers.onScroll(event);
switch (headerSize) {
case "big":
setHeaderVisible(false);
return;
case "small":
setHeaderVisible(true);
return;
case "default":
default:
const scrollY = event.nativeEvent.contentOffset.y;
if (Scroll_Distance < scrollY == headerVisible) return;
LayoutAnimation.configureNext({
duration: 100,
update: { type: "easeOut" },
});
setHeaderVisible(Scroll_Distance < scrollY);
break;
}
};
return (
<View {...containerProps}>
<View style={{ zIndex: 1 }}>
<Animated.View
style={[
styles.header,
headerVisible ? shotHeaderStyle.on : shotHeaderStyle.off,
]}
>
{viewHeader ? <></> : shortHeader}
</Animated.View>
<Animated.View
style={[
styles.header,
headerVisible ? longHeaderStyle.off : longHeaderStyle.on,
]}
>
{viewHeader ? <></> : longHeader}
</Animated.View>
<Animated.View style={headerVisible ? StickyStyle.off : StickyStyle.on}>
{topStickyContent}
</Animated.View>
</View>
<NativeViewGestureHandler
simultaneousHandlers={scrollHandlers.simultaneousHandlers}
>
<ScrollView
nestedScrollEnabled
ref={scrollHandlers.ref}
onLayout={scrollHandlers.onLayout}
scrollEventThrottle={scrollHandlers.scrollEventThrottle}
style={{ backgroundColor: "white", zIndex: 0 }}
stickyHeaderIndices={[1]}
onScroll={onScroll}
>
<View style={{ height: Scroll_Distance, flexDirection: "column" }} />
{topStickyContent && (
<View
style={{
paddingTop: Min_Header_Height + 40,
flexDirection: "column",
}}
index={1}
/>
)}
{children}
</ScrollView>
</NativeViewGestureHandler>
</View>
);
};