React native scrollview(flatlist) scroll stops when height changes(animates) - react-native

I have above screen, and I want header to disappear with animation
when flatlist scrolls down, and appear with scrolls up.(tab must be visible)
Thank of Facebook -> Feed header animation when scrolling.
I am using below code to animate header:
const animatedHeader = {
opacity: this.state.animatedHeaderValue.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [0, 0, 1],
}),
height: this.state.animatedHeaderValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 57 + Constants.statusBarHeight],
}),
};
whenever header height changes, flatlist will stop scrolling and wait until height change is over.
how to hack this?

Related

Dynamic Animation translate limits on Slider

I have a task where I'm creating a 'slider' essentially, but it has two bars on the same slider. What I'm trying to do is move those sliders up and down the y axis but the bar you are sliding is not to move past it's twin. eg. Top Slider is not to move past the Bottom Slider and visa versa.
My thought is then that the output limits along the translateY will be dynamic.
So far, attempts have shown to have odd behaviours.
View Image Example
I have tried the top and bottom bars as pan responders with there movements on the y-axis, saved in a useState and that state is added to the outputRange on the translateY
`<Animated.Image
resizeMode="stretch"
source={Theme.defaultImages.progressBar}
style={{
width: hp(100) / 2.8,
height: hp(4),
position: 'absolute',
alignSelf: 'center',
transform: [
{
translateY: pan.y.interpolate({
inputRange: [0, height],
outputRange: [0, topBarYPositionState], //useState is added here for dynamic limit.
extrapolate: 'clamp',
}),
},
d],
}}
{...PanResponder.panHandlers}
/>`

How to get image to take up whole screen on press using Transform with React Native

I'm creating a chat app and want to make a picture take up the whole screen when it is clicked on like in other chat apps. The code I have so far scales it to the whole screen and centers it horizontally, but only because I know where on the X axis it is starting at and then calculate the translateX from there. The problem is that, for the Y axis, an image can be anywhere on the screen when it is clicked so I can't do the same thing I did for translateX. How can I get the Y position of the image to calculate how much I need to translate it on the Y Axis.
I know there were similar solutions that use spring, but I like the look of the image expanding from where it begins rather than it coming up from the bottom.
Here is my current code:
<Animated.View
style={[
styles.fadingContainer,
{
transform: [
{
scale: Anim.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [1, 1.5, 2],
}),
},
{
translateX: Anim.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [
0,
Dimensions.get("window").width / 16,
Dimensions.get("window").width / 8,
],
}),
},
{
translateY: Anim.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [
** What do I put here? **
],
}),
},
],
},
]}
>
<Text style={styles.fadingText}>Fading View!</Text>
</Animated.View>

TouchableOpacity is not working when Transform Animation is applied

Below code is to render a Touchable button with Transform Animation.
const { scrollY, headerScrollDistance } = this.state;
const profileImageTranslateX = scrollY.interpolate({
inputRange: [0, headerScrollDistance],
outputRange: [0, -(ScreenWidth /2) + 32],
extrapolate: 'clamp',
});
const profileImageTranslateY = scrollY.interpolate({
inputRange: [0, headerScrollDistance],
outputRange: [0, -11],
extrapolate: 'clamp',
});
const profileImageScale = scrollY.interpolate({
inputRange: [0, headerScrollDistance / 2, headerScrollDistance],
outputRange: [1, 0.8, 0.6],
extrapolate: 'clamp',
});
return (
<Animated.View
style={[
Styles.animatedView.profileStyle,
{
transform: [
{ translateX: profileImageTranslateX },
{ translateY: profileImageTranslateY },
{ scale: profileImageScale }
]
}
]}
>
<TouchableOpacity activeOpacity={0.5} onPress={() => this.props.history.push('./profilePhotoChanger')}>
<ImageComp profileImageUrl={profileimageurl} imageStyle={Styles.homePageImageStyle} />
</TouchableOpacity>
</Animated.View>
);
As page scrolls, Animation applies to Touchable button. Button is working as expected when transform animation is not applied. But not working when animation is applied. If page comes back to it's normal state(i.e scrolling back) then button works as expected.
Is it normal behaviour in react-native that TouchableOpacity's onPress wont't work when animation applied? or is something wrong with my code?
You can try one of the following option if it works for you
1- import { TouchableOpacity } from 'react-native-gesture-handler';
2- Change height of Animated.View which contain TouchableOpacity (to
fit size of TouchableOpacity)
3- By moving <Animated.View> inside TouchableOpacity
Look like there is open discussion on Touchableopacity not working inside Animated.View

Prevent negative animated value on scroll

I have header collapsed on scroll event. On ios scroll offset value can be negative and it cause problem.
Is there any way to prevent animated value being negative?
Here is my code
const ScrollYDiffClamp = Animated.diffClamp(positionY, 0, 60);
const headerTranslate = ScrollYDiffClamp.interpolate({
inputRange: [0, 1],
outputRange: [0, -1],
});
return (
<>
<Header style={{transform: [{translateY: headerTranslate}]}}/>
<Animated.ScrollView
onScroll={Animated.event([{nativeEvent: {contentOffset: {y: positionY}}}], {
useNativeDriver: true,
})}>
</Animated.ScrollView>
</>
)
I believe you can disable bounces on your Animated.ScrollView
bounces={false}
or you can add additional interpolate and fix this issue
const headerHeight = 50;
const clampedScrollY = scrollY.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
extrapolateLeft: 'clamp',
});
const diffClampScrollY = Animated.diffClamp(clampedScrollY, 0, headerHeight);
const translateY = diffClampScrollY.interpolate({
inputRange: [0, headerHeight],
outputRange: [0, -headerHeight],
extrapolate: 'clamp',
});
Try adding this to your interpolation configuration.
extrapolate: "clamp"
Oleskii's answer worked for me, the only issue I was having was on the bottom the issue that this solved on the top was still happening. Just adding more to the max height seems to have resolved the issue though. Something like:
const diffClampScrollY = Animated.diffClamp(clampedScrollY, 0, headerHeight + 300);
the bouncing that happens in the ScollView seems to be covered with 300 added to the max output of the diffClamp

Animating Height when scrolling a ScrollView

So im trying to animate a view by changing the view's height when a user scrolls a specific scrollview. It looks fine on IOS although it has some jitter going on but the flickering is very visible on android. Here is my code.
Scrollview's on scroll
onScroll={(e) => {
this.state.profileTabAnimatedValue.setValue(e.nativeEvent.contentOffset.y);
}}
height interpolate object
const headerHeight = this.state.profileTabAnimatedValue.interpolate({
inputRange: [0,1],
outputRange: [1,100]
});
I will then apply the headerHeight to a view to adjust it's height
Try using the Animated event method:
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.profileTabAnimatedValue}}}]
)}
Also, if you don't want some weird behaviours like negative height or so, add this in your interpolation:
const headerHeight = this.state.profileTabAnimatedValue.interpolate({
inputRange: [0,1],
outputRange: [1,100]
extrapolate: 'clamp'
});
Last thing is you can play a bit with throttling your events firing on your ScrollView with scrollEventThrottle, just read this