# [react native] sticky header
{%youtube hQQZjiW5thk %}
```jsx
import React from "react";
import { Text, View, Dimensions, SafeAreaView, StatusBar } from "react-native";
import Animated, { Extrapolate, interpolate } from "react-native-reanimated";
const HeaderImage = ({ y }) => {
// 因為 要解決 zIndex 的問題,所以設定 Header 為 absolute
// then Header 高度為 50 所以設定開始位置為 50
const top = Animated.interpolate(y, {
inputRange: [0, 50], // 線性速度
outputRange: [50, 0], // 位置開始,結束
extrapolate: Extrapolate.CLAMP,
useNativeDriver: true,
});
// 也可以三個
// const top = y.interpolate({
// inputRange: [0, 40, 100], // 線性速度
// outputRange: [40, 30, 0], // 位置開始,結束
// extrapolate: "clamp",
// useNativeDriver: true,
// });
return (
<Animated.Image
source={{ uri: "https://source.unsplash.com/user/erondu/1600x900" }}
style={[
{
width: Dimensions.get("screen").width,
height: (900 / 1600) * Dimensions.get("screen").width,
},
{
transform: [{ translateY: top }],
},
]}
/>
);
};
const App = () => {
const scrollY = new Animated.Value(0);
const listViewTop = scrollY.interpolate({
inputRange: [0, 250],
outputRange: [60, 0],
extrapolate: "clamp",
useNativeDriver: true,
});
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView style={{ flex: 1 }}>
<View style={{ width: Dimensions.get("screen").width }}>
<View
style={{
position: "absolute",
top: 0,
left: 0,
height: 50,
zIndex: 0,
width: Dimensions.get("screen").width,
backgroundColor: "dodgerblue",
justifyContent: "center",
paddingLeft: 20,
}}
>
<Text>HEADER</Text>
</View>
<HeaderImage y={scrollY} />
<Animated.ScrollView
// overScrollMode={"never"}
scrollEventThrottle={16}
onScroll={Animated.event([
{
nativeEvent: { contentOffset: { y: scrollY } },
},
])}
style={{ zIndex: 10 }}
>
<Animated.View
style={{
paddingHorizontal: 20,
height: 2000,
transform: [
{
translateY: listViewTop,
},
],
}}
>
<View style={{ marginBottom: 30 }}>
<Text style={{ fontSize: 20, fontWeight: "bold" }}>標題一</Text>
<Text>
Incididunt amet aliqua pariatur quis cupidatat fugiat. Ea quis
est cillum id ex laboris eu ea adipisicing. Nulla ex officia
nisi adipisicing commodo. Elit sint eiusmod ut non elit irure
sint est nulla deserunt tempor.
</Text>
</View>
<View style={{ marginBottom: 30 }}>
<Text style={{ fontSize: 20, fontWeight: "bold" }}>標題二</Text>
<Text>
Incididunt amet aliqua pariatur quis cupidatat fugiat. Ea quis
est cillum id ex laboris eu ea adipisicing. Nulla ex officia
nisi adipisicing commodo. Elit sint eiusmod ut non elit irure
sint est nulla deserunt tempor.
</Text>
</View>
<View style={{ marginBottom: 30 }}>
<Text style={{ fontSize: 20, fontWeight: "bold" }}>標題三</Text>
<Text>
Incididunt amet aliqua pariatur quis cupidatat fugiat. Ea quis
est cillum id ex laboris eu ea adipisicing. Nulla ex officia
nisi adipisicing commodo. Elit sint eiusmod ut non elit irure
sint est nulla deserunt tempor.
</Text>
</View>
<View style={{ marginBottom: 30 }}>
<Text style={{ fontSize: 20, fontWeight: "bold" }}>標題四</Text>
<Text>
Incididunt amet aliqua pariatur quis cupidatat fugiat. Ea quis
est cillum id ex laboris eu ea adipisicing. Nulla ex officia
nisi adipisicing commodo. Elit sint eiusmod ut non elit irure
sint est nulla deserunt tempor.
</Text>
</View>
</Animated.View>
</Animated.ScrollView>
</View>
</SafeAreaView>
</>
);
};
export default App;
```
### 參考的網站與文章
- https://medium.com/hackernoon/react-native-animated-header-using-animated-and-scrollview-9749255c149a
- https://www.youtube.com/watch?v=xutPT1oZL2M&t=717s