I'm animating a bottom-sheet using react-native-reanimated(v2.2.0) also I need to change opacity of one view inside bottom-sheet with the animation.
Expected behavior.
Opacity of the view diereses when bottom-sheet came up. so the opacity of view should be 1 on bottom-sheet closed and opacity is 0 when bottom-sheet opens.
Problem
I'm using interpolate to get opacity value between 0 and 1 relatively with the bottom-sheet top position and using useAnimatedStyle to animate the opacity.
const derived = useDerivedValue(() => {
const opacity = interpolate(
top.value,
{
inputRange: [top.value, 0],
outputRange: [0, 1],
},
[top.value],
);
return opacity.value;
});
const style = useAnimatedStyle(() => {
return {
opacity: derived.value,
};
});
Then I'm using above style on my Animated.View
<PanGestureHandler onGestureEvent={gestureHandler}>
<Animated.View style={[BottomSheetStyles, bottomSheetAnimatedStyles]}>
<Animated.View //view i need to change opacity
style={[MinPlayerStyles, style]}
onPress={() => (top.value = withSpring(0, SPRING_CONFIG))}>
<Text>Card</Text>
</Animated.View>
</Animated.View>
</PanGestureHandler>
I solve this problem by only using useAnimatedStyle and interpolate.
Calculating opacity depending on bottom-sheet top value and giving it the range between 0 and 1 and returning opacity style.
const minPlayerAnimatedStyles = useAnimatedStyle(() => {
const opacity = interpolate(
top.value,
[0, top.value],
[0, 1],
);
return {
opacity,
};
});
Now opacity changing on open bottom-sheet and close bottom-sheet but the opacity value not animating like a fading effect. What i want is to fade the opacity.
Currently opacity sets to 1 as soon as the bottom-sheet starts. What i expected is to fade opacity.
Related
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
I am using Animated.View to change the header height.
It works well in ios but in android, when I scroll slowly the entire view is shaking.
1) First I set the state
this.state = {
scrollY:new Animated.Value(0)
}
2) Inside the render() I render the height of the view I want to animate.
const HeaderHeight = this.state.scrollY.interpolate({
inputRange: [0, 100],
outputRange: [100, 0],
extrapolate: 'clamp'
})
3) I set my Header like this:
<Animated.View style={{width:'100%', height:HeaderHeight, backgroundColor:'transparent', justifyContent:'flex-end'}}>
...
</Animated.View>
4) Inside the scrollview:
<ScrollView
scrollEventThrottle={16}
onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }])}
>
As you could see from the gif file when I slowly scroll the view the screen is shaking. This is happening in android. On ios it works fine.
Any idea how to fix this?
Any comments or advice would be really helpful :)
Your inputRange [0,100] and outputRange[100,0] have a ratio of 1.
This means that for each pixel you move in the ScrollView, your HeaderHeight will be reduced by one, which sounds great but the value you get from the scrollview event is not an integer, is a double and based on those tiny digits it will try to "aspect ratio" your outputRange and this is quite sensitive in Android and therefore the shaking.
Increase your inputRange to [0, 200] so it has a ratio of 2 related to the outputRange. This will remove the shaking.
It can be a little tricky but try to avoid set translate prop to FlatList`s style, or component that wrap Flatlist, jumps will disappear. For adding empty space before first item you can set contentContainer={{paddingTop:}}. It was in my case, hope this help someone.
Make your scrollview animated.
<Animated.ScrollView
style={{flex: 1}}
onScroll={Animated.event([
{ nativeEvent: { contentOffset: { y: this.scrollY } } }
])}
>
...
...
</Animated.ScrollView>
I want to animate a view's(say abcView) position based on main container flat list scroll offset. If the user scrolls down, abcView's position should move to bottom proportionately(vice versa when user scrolls back up). The position of abcView should change in proportion to the flatlist offset and not in one go. I want to use animated API but need ideas how to proceed with this.
You could try below functional component
function SomeComponent() {
const [scrollY] = useState(new Animated.Value(0));
const translateY = scrollY.interpolate({
inputRange: [0, 150],
outputRange: [0, 150],
extrapolate: 'clamp',
useNativeDriver: true,
});
return (
<View>
<Animated.FlatList
onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: scrollY } } }])}
/>
<Animated.View
style={{
transform: [{ translateY: translateY }],
}}
></Animated.View>
</View>
)
}
Since you said you need ideas, I think what you are looking for is the parallax effect. You can either go ahead building your own or you can search for such libraries e.g. react-native-parallax-header
I have a scrollview on top of which i display a header. My goal is to animated so that when the user scrolls down, the header collapse and when the view scrolls up, the header expands.
I found plenty of exemple where the user has to scroll all the way up for the header to expand. What i'd like is for the header to expand as soon as the scroll view scrolls up.
How can I achieve this?
Here is what I have so far:
type State = { scrollY: Animated.Value };
....
headerHeight = this.state.scrollY.interpolate({
inputRange: [
0, 60
],
outputRange: [60, 0],
extrapolate: "clamp"
});
<Animated.View style={{ height: headerHeight, backgroundColor: "#F0f" }}
>
<ScreenHeader
ref={this.screenHeaderRef}
onTouchAvatar={this.handleOpenProfile}
onTouchNotifications={this.handleOpenNotification}
user={currentUser}
newNotifications={this.props.newNotifications}
/>
</Animated.View>
<WrappedComponent
onScroll={Animated.event([
{
nativeEvent: {
contentOffset: {
y:
this.state.scrollY
}
}
}
])}
onMomentumScrollEnd={this.handleMomentumScrollEnd}
{...this.props}
/>
So you are right about the animating the translateY property. So I did it a bit different way for sake of this question (Poorly, sorry about that, you need to play around a bit with this to get the right animation).
So try to set the style of the animated view's translateY to 0;
<Animated.View
style={[{
transform: [
{
translateY: this.transform
}
]
}, {
backgroundColor: 'red'
}]}
>
Then on scroll set it to -100 or whatever your header height.
later when the user comes back up, towards the top 0, you set it up to 0.
This will do the trick, hopefully.
Here's a small example, sorry for getting back late. :)
https://snack.expo.io/#subkundu/header-hideshow
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