'React Native Animating List of texts
I have an array of texts that I want to flash on a blank screen, one after the other with animations. Something like:
state = {
meditations: ["Take a deep breath", "embrace this feeling", "breath
deeply", ...]
}
I want to show only one string at a time, and animate their opacity. So a string fades in and fades out, then the next string, and so on.
I am new to react native and quite confused about how to go about this. Please, how may I approach this, I have read the docs but still not clear how to.
Below is what I have tried, I modified this from the docs but it shows everything at once. I'm still trying to see how I can make them animate one after the other, showing only one at a time. Thanks for your help in advance.
import React from 'react';
import { Animated, Text, View } from 'react-native';
class FadeInView extends React.Component {
state = {
fadeAnim: new Animated.Value(0), // Initial value for opacity: 0
}
renderMeditations() {
let { fadeAnim } = this.state;
return this.props.meditations.map((meditation, index) => {
Animated.timing( // Animate over time
this.state.fadeAnim, // The animated value to drive
{
toValue: 2, // Animate to opacity: 1 (opaque)
duration: 10000, // Make it take a while
}
).start(() => {
this.setState({ fadeAnim: new Animated.Value(0) })
}); // Starts the animation
return (
<Animated.Text // Special animatable View
key={index}
style={{
...this.props.style,
opacity: fadeAnim, // Bind opacity to animated value
}}
>
{meditation}
</Animated.Text>
)
})
}
render() {
return (
<View style={{flex: 1}}>
{this.renderMeditations()}
</View>
);
}
}
export default class App extends React.Component {
state = {
meditations: ["Take a deep breath", "Calm down", "Relax", "Tell yourself all will be fine"]
}
render() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<FadeInView meditations={this.state.meditations} style={{fontSize: 28, textAlign: 'center', margin: 10}} />
</View>
)
}
}
Solution 1:[1]
The map function executes all at once so basically you are rendering/returning all 3 items at the same time. I understand that your issue is that the animation is working tho.
If what you want is to show one text, then the other and so on I suggest iterating the index of your text array instead of using the map function.
Something like:
- Execute Animation
- Increase Index
- Index = 0 if you are at the end of the array.
In a loop. Check setInterval, it might help you.
Solution 2:[2]
After much toil with this, I was able to solve it with react-native-animatable like so:
import React from "react";
import {
View,
Text,
Animated
} from "react-native";
import * as Animatable from 'react-native-animatable';
class VideoScreen extends React.Component {
state = {
meditations: ["Take a deep breath", "embrace this feeling", "breath
deeply"],
index: 0
};
render() {
const { meditations, index } = this.state;
return (
<View style={{flex: 1}}>
<Animatable.Text
key={index}
animation={'fadeIn'}
iterationCount={2}
direction="alternate"
duration={2000}
onAnimationEnd={() => {
if (this.state.index < this.state.meditations.length - 1) {
this.setState({ index: this.state.index + 1});
}
}}
style={{
position: "absolute",
left: 0, right: 0,
bottom: 40
}}>
{meditations[index]}
</Animatable.Text>
</View>
);
}
}
export default VideoScreen;
Solution 3:[3]
For the function components:-
we can use the above-metioned solutions. I am writing a function hopefully it will help you display a looping text with the animation
We will use this package for the animation https://github.com/oblador/react-native-animatable.
import {StyleSheet} from 'react-native';
import React, {useState} from 'react';
import * as Animatable from 'react-native-animatable';
const UserMessage = () => {
const [index, setIndex] = useState(0);
const meditations = [
'Take a deep breath',
'embrace this feeling',
'breath deeply',
];
return (
<Animatable.Text
key={index}
animation={'fadeIn'}
iterationCount={2}
direction="alternate"
duration={2000}
onAnimationEnd={() => {
if (index < meditations.length - 1) {
setIndex(index + 1);
} else {
setIndex(0);
}
}}
style={styles.messageStyle}>
{meditations[index]}
</Animatable.Text>
);
};
export default UserMessage;
const styles = StyleSheet.create({
messageStyle: {
textAlign: 'center',
fontSize: 18,
fontWeight: '500',
width: '80%',
color: '#1C1C1C',
marginBottom: 20,
minHeight: 50,
alignSelf: 'center',
},
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | sebastianf182 |
| Solution 2 | Awa Desmoline |
| Solution 3 | Sachin Saini |
