React-native accordion / toggle functionality with slide animation - react-native

I want to have accordion / toggle functionality which will have slide or similar kind of animation
I have tried out this solution. But while closing animation do not work
constructor(props) {
super(props);
height: new Animated.Value(0)
};
}
_toggle = () => {
this.state.height.setValue(0);
Animated.spring(
this.state.height,
{
toValue: expanded ? 200 : 0,
duration: 200
}
).start();
}
Thanks in advance for your answers!!!

The first line in _toggle sets the value to 0.
That's why when it's expanded, the animation goes from 0 to 0.
Removing that line should sort it.

Related

React Native animate position (Left & Right) using useNativeDriver

Is it possible to extend ReactNative to allow animation of an element's position using the native driver.
Whilst you can animate via translateX, in this case, the size of the element is to be reduced adding by changing both its left and right style parameters.
Neither left, right, marginLeft, marginRight, paddingLeft nor paddingRight are supported for native animations. Is there a way around this or some ingenious idea involving scaling that won't distort the element.
export class ViewScreen extends React.Component {
constructor(props) {
super(props);
this.state= {
scrollY: new Animated.Value(0)
}
}
render() {
var VSStickyElementsMargin = this.state.scrollY.interpolate({
inputRange: [0, 44],
outputRange: [0, 4]
});
return (
<Animated.ScrollView
onScroll={Animated.event([
{ nativeEvent: { contentOffset: { y: this.state.scrollY } }}],
{ useNativeDriver: true }
)}>
<Animated.View style={[
{left: VSStickyElementsMargin},
{right: VSStickyElementsMargin}
]}>
<Text>I am content that is not to become distorted</Text>
</Animated.View>
</Animated.ScrollView>
)
}
}
There is no way to use native driver on properties that are not transforms or opacity.
If I understand what you are trying to achieve correctly you should use use translateX to move the element outwith its parent and animate it back into view when you need to, use overflow hidden on the parent.
Alternatively if this is not the effect you want try looking at the layoutanimation api as you can get better performance using it to drive values than animating non transform/opacity properties.

How do I start a `spring` animation with react-native-reanimated in a declarative way?

I have a simple Animated.View that I move based on the user's finger, my component looks like this:
return (
<View
style={styles.container}
>
<PanGestureHandler
ref={this.panRef}
onGestureEvent={this.handlePan}
onHandlerStateChange={this.handlePan}
>
<Animated.View
style={[
styles.parent,
{
transform: [
{ translateX: this.X },
],
},
]}
>
<MyAwesomeComponent />
</Animated.View>
</PanGestureHandler>
</View>
The problem is, I want to create a declarative method called scrollToPosition(position, animated)
It now looks like this:
scrollToPosition = (position, animated = false) => {
if (animated) {
// TODO: What to do now?
} else {
this.X.setValue(position);
}
}
, it works without an animation, but my goal now is to add a way to animate the value with an Ease too.
If we were on the react-native Animated world, we'd do something like this:
Animated.spring(this.X, {
toValue: position,
}).start();
but how do I do the same thing with react-native-reanimated.
Please don't waste time explaining about the UI vs JS realm, I know about it, and I do want to take advantage of running animations in the UI thread, I just don't know how to run this animation declaratively after the user i.e taps a button.
Thanks
In using Animated.spring in reanimated, you should define the config as without that, it won't work
const config = {
damping: 15,
mass: 1,
stiffness: 150,
overshootClamping: false,
restSpeedThreshold: 0.001,
restDisplacementThreshold: 0.001,
}
Animated.spring(this.X, {
toValue: position,
...config
}).start();

How should I animate a React native component with the library "Animated"

I'm trying to animate some component. I Just want to change the size of the width of a View. I'm been looking the simplest way to make simple animations.I'm using the library "Animated".I can't make this work
I'm looking for some tutorials and it doesn't work.For some reason the code doesn't reconize the initial width of a "Animated.View" it is a variable declarated on the constructor just like this "animationwidth = new Animated.Value(11);".I dont know if the problem is in the declaration of the variable, in the style of the "Animated.View"or in the "animated.timing" function
import React, { Component } from 'react';
import {Animated,Text,Alert,View, Image, Button} from 'react-native';
export default class Game extends Component {
constructor(props) {
super(props);
this.state = {
opa: 1
};
animationwidth = new Animated.Value(11);
}
componentDidmount(){
Animated.timing(this.animationwidth, {
toValue: 300
}).start()
}
render(){
return(
<View style={{flex:1,alignItems:'center',backgroundColor:'green',justifyContent:'center'}}>
<Animated.View style={{ height:250, width:this.animationwidth ,backgroundColor:'blue'}}/>
</View>
)
}
}
You forgot to include state to animationwidth:
change your Animated.View component style like this:
<Animated.View style={{ height:250, width:this.state.animationwidth ,backgroundColor:'blue'}}/>
if does not animate. add duration property inside Animated timing function and also add state to animationwidth like this :
Animated.timing(this.state.animationwidth, {
toValue: 300,
duration: 1000
}).start()
}
base on your code the width of your View will start at 11 and end with 300
The problem here is the render method not called again as the state is not updated again. You need to update some state variable in componentDidmount and thus the render method will call again.
Add a state variable and toggle that variable in componentDidMount
this.state = {
isShowing : false
};
componentDidmount(){
this.setState({isShowing:!this.state.isShowing})
Animated.timing(this.animationwidth, {
toValue: 300
}).start()
}

How can I implement animation in my flatlist?

I am using Flatlist in my rn project and when I push new data into my flatlist, my item 1 will automatically move from position A to position B. But my question is I don't want it to just change the position, I want to use animation to move my item(from position A to position B). How can I implement that? Thank you!
Please check the demo picture and video from the link down below:
https://photos.app.goo.gl/WypswNyA38A2EAPQA
https://photos.app.goo.gl/Ev1RYMduDj7mxrHn7
You can use Animated component to do the animation. As per your attached video, 2 steps animation comes into play, one which pushes the items up in the list and another one which increases the opacity of the list item. A simple approach would be to add the list item with height 0 and increase the height to desired height using animation, this will complete the first step. Once the first step is completed, control the opacity to go from 0 to 1.
Next, you need to start the animation when the list item is added to the list, componentDidMount is the right place to do so. Please consider the following component which does the above steps.
import React from 'react';
import { Animated } from 'react-native';
class AnimatedListItem extends React.Component {
constructor(...props) {
super(...props);
this.state = {
height: new Animated.Value(0),
opacity: new Animated.Value(0)
};
}
componentDidMount() {
Animated.sequence([
Animated.timing(
this.state.height,
{
toValue: this.props.height,
duration: this.props.duration || 1000
}
),
Animated.timing(
this.state.opacity,
{
toValue: 1,
duration: this.props.duration || 1000
}
)
]).start();
}
render() {
const { height, opacity } = this.state;
return (
<Animated.View
style={{
...this.props.style,
height: height,
opacity: opacity
}}
>
{this.props.children}
</Animated.View>
);
}
}
export default AnimatedListItem;
In the above snippet, two animations are passed to Animated.sequence([...]) method to animate one after the other.
You can now use the above component in the renderItem method like
renderItem = () => {
return (
<AnimatedListItem height={50} duration={800} style={...}>
/* render actual component here */
</AnimatedListItem>
);
}
Hope this will help!
Note: This is a bare minimum example to achieve what you are looking for.

New animation after setState - React Native

I don't find the answer to my problem for my react native app.
If you have an idea how to achieve that, that would be great :)
What I'm trying to do:
In a page, when I press somewhere, I want to display an animation (for example a square apparition) on the press position.
What I have achieved:
When I click, a square is display with an animation on the right position.
But when i click somewhere else, The position of the square changes but the animation doesn't restart.
What I have tried:
To do the animation, I place a < View/> (with position: 'absolute') on the press position.
This < View/> is embeded in a component that I call 1 time in my App render:
<ClickAnimation x={item.x} y={item.y}/>
where item.x and item.y are are the coordinate.
This is the code of my component:
import React from 'react';
import {Animated, View} from 'react-native';
export default class ClickAnimation extends React.Component {
state = {
scaleAnim: new Animated.Value(0)
};
componentWillMount() {
Animated
.timing(this.state.scaleAnim, {
toValue: 2,
duration: 500
})
.start();
}
componentWillUpdate(nextProps) {
if (nextProps.x != this.props.x && nextProps.y != this.props.y) {
this.setState({
scaleAnim: new Animated.Value(0)
})
}
}
componentDidUpdate() {
console.log("componentDidUpdate",this.state.scaleAnim)
Animated
.timing(this.state.scaleAnim, {
toValue: 2,
duration: 500
})
.start();
}
render() {
return (<Animated.View
style={{
position: "absolute",
top: this.props.y,
left: this.props.x,
width: 50,
height: 50,
backgroundColor: "red",
transform: [
{
scaleY: this.state.scaleAnim
}, {
scaleX: this.state.scaleAnim
}, {
translateX: -25
}, {
translateY: -25
}
]
}}/>);
}
}
The console.log in componentDidUpdate give me for each click 2 logs:
{_children: Array(2), _value: 2, ..., _animation: null…}
{_children: Array(2), _value: 0,..., _animation: null…}
I really don't know what to do next.
PS: In NativeScript, that was more easy. I had just to add the new component to the DOM.
According to React docs you cannot this.setState() inside componentWillUpdate(),if you need to update state in response to a prop change, use componentWillReceiveProps(nextProps) instead.
https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops
Read the above link for more details on that and check its caveats.
I hope this is what is causing the problem
It seems that EXPO XDE make the application too slow and this is why the animation part doesn't work properly.
I have found the solution.
This come with this issue:
https://github.com/facebook/react-native/issues/6278
I had seen it and this is why I wrote first 0,001. But 0,001 is still to little. With 0,01 it works great.
So the answer is:
Just replace 0 by 0.01 because it was too little.