Any code example of how to implement Animated.diffClamp?
I'm trying to create a header scroll animation like the one featured in the google play app. I already hide the header when you start scrolling down, but the problem is that I want to show the header again as soon as you start scrolling up, it shows only when you reach the top of the view.
class Services extends Component {
constructor(props){
super(props);
this.state = {
scrollY : new Animated.Value(0),
}
}
renderScrollViewContent(){
return (
<View style={styles.scrollViewContent}>
</View>
)
}
render() {
const headerHeight = this.state.scrollY.interpolate({
inputRange: [0, 60],
outputRange: [0, -60],
extrapolate: 'clamp'
});
return (
<View style={styles.container}>
<ScrollView style={styles.container}
scrollEventThrottle={16}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.scrollY}}}]
)}
>
{this.renderScrollViewContent()}
</ScrollView>
<Animated.View style={[styles.header, {top: headerHeight}]}>
<View style={styles.bar}>
<Text style={styles.title}>Title</Text>
</View>
</Animated.View>
</View>
);
}
}
We added this exactly for this use case. Here's the doc page https://facebook.github.io/react-native/docs/animated.html#diffclamp
I also recommend using it with a translate transform (better perf and can be used with native driver). Here's your example render using it:
const headerTranslate = Animated.diffClamp(this.state.scrollY, 0, 60)
.interpolate({
inputRange: [0, 1],
outputRange: [0, -1],
});
return (
<View style={styles.container}>
<ScrollView style={styles.container}
scrollEventThrottle={16}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.scrollY}}}]
)}
>
{this.renderScrollViewContent()}
</ScrollView>
<Animated.View style={[styles.header, {transform: [{translateY: headerTranslate}]}]}>
<View style={styles.bar}>
<Text style={styles.title}>Title</Text>
</View>
</Animated.View>
</View>
);
How it works is we pass the scroll position to diffClamp so it is clamped between 0 and 60, after we use interpolate to make the value negative (we want it to translate up).
Here is an example with a header appearing from the top, only after the user has scrolled to a minimum Y position, and solving the overscroll/bouncing problem by clamping.
const minScroll = 100;
const clampedScrollY = scrollY.interpolate({
inputRange: [minScroll, minScroll + 1],
outputRange: [0, 1],
extrapolateLeft: 'clamp',
});
const minusScrollY = Animated.multiply(clampedScrollY, -1);
const translateY = Animated.diffClamp(
minusScrollY,
-AnimatedHeaderHeight,
0,
);
const opacity = translateY.interpolate({
inputRange: [-AnimatedHeaderHeight, 0],
outputRange: [0.4, 1],
extrapolate: 'clamp',
});
More details: https://stackoverflow.com/a/51638296/82609