Reputation: 487
I am trying to change some code that is using the old Animated within react native. The scenario is that I have a basic flatlist that has only 4 test items. When one is clicked it simply performs a basic animation on only the clicked item.
I have managed to swap it over to the new reanimated but it is not isolating the one item when clicked? I have changed the animation but this is purely because of the example given in the official code because eventually I would like to play with the selected item more.
It is sort of frustrating because I can not work out why it is animating all the items?
Here is the working code with the old Animated working :-
class Item extends Component {
constructor() {
super();
this.state = { animation: new Animated.Value(1) };
}
startAnimation (){
const animations = [
Animated.timing(this.state.animation, {
toValue: 1.5,
duration: 500
}),
Animated.timing(this.state.animation, {
toValue: 1,
duration: 500
}),
Animated.timing(this.state.animation, {
toValue: 2,
duration: 500
}),
Animated.timing(this.state.animation, {
toValue: 1,
duration: 500
}),
];
Animated.sequence(animations).start()
}
render() {
const { values, index } = this.props;
return (
<Animated.View style={{margin: 10, transform:[{scale: this.state.animation}]}}>
<TouchableOpacity onPress={() => {this.startAnimation(); alert(index);} }>
<Text>{values.name}</Text>
</TouchableOpacity>
</Animated.View>
);
}
}
export default class App extends Component {
constructor() {
super();
this.state = {
items: [
{ id: 1, name: 'name 1' },
{ id: 2, name: 'name 2' },
{ id: 3, name: 'name 3' },
{ id: 4, name: 'name 4' },
]
};
}
render() {
return (
<View style={styles.container}>
<FlatList
numColumns={4}
data={this.state.items}
renderItem={({item, index}) => <Item key={index} values={item} index={index} />}
/>
</View>
);
}
}
and with the new reanimated version :-
const ANGLE = 10;
const TIME = 100;
const EASING = Easing.elastic(1.5);
const items = [
{ id: 1, name: 'name 1' },
{ id: 2, name: 'name 2' },
{ id: 3, name: 'name 3' },
{ id: 4, name: 'name 4' },
]
export default function App() {
const rotation = useSharedValue(0);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ rotateZ: `${rotation.value}deg` }],
}));
const handlePress = () => {
rotation.value = withSequence(
// deviate left to start from -ANGLE
withTiming(-ANGLE, { duration: TIME / 2, easing: EASING }),
// wobble between -ANGLE and ANGLE 7 times
withRepeat(
withTiming(ANGLE, {
duration: TIME,
easing: EASING,
}),
7,
true
),
// go back to 0 at the end
withTiming(0, { duration: TIME / 2, easing: EASING })
);
};
const Item = ({item}) => {
return (
<View style={styles.item}>
<Animated.View style={animatedStyle}>
<Text onPress={handlePress} style={{margin: 10}}>{item.name}</Text>
</Animated.View>
</View>
)
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
<FlatList
numColumns={4}
data={items}
renderItem={Item}
keyExtractor={item => item}
/>
</View>
</SafeAreaView>
);
}
I have tried adding this but it just stop everything. In the first one, the click refers to this , do I need to add this into the click?
const animatedStyle = new useAnimatedStyle(() => ({
Upvotes: 0
Views: 899
Reputation: 487
I have it working, I had to place the animation directly into the ITEM, so each ITEM has its own animate sequence. It works but something tells me there is something else I could do to reduce the amount of code?
import React, { useState, useEffect } from 'react';
import { Text, View, StyleSheet, FlatList, TouchableOpacity, SafeAreaView, Image, Pressable } from 'react-native';
import Animated, {
useSharedValue,
withTiming,
Easing,
useAnimatedStyle,
withRepeat,
withSequence,
} from 'react-native-reanimated';
const ANGLE = 10;
const TIME = 100;
const EASING = Easing.elastic(1.5);
const Item = ({ item }) => {
const rotation = useSharedValue(0);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ rotateZ: `${rotation.value}deg` }],
}));
const handlePress = () => {
rotation.value = withSequence(
// deviate left to start from -ANGLE
withTiming(-ANGLE, { duration: TIME / 2, easing: EASING }),
// wobble between -ANGLE and ANGLE 7 times
withRepeat(
withTiming(ANGLE, {
duration: TIME,
easing: EASING,
}),
7,
true
),
// go back to 0 at the end
withTiming(0, { duration: TIME / 2, easing: EASING })
);
};
return (
<Animated.View style={animatedStyle}>
<Pressable onPress={() => {handlePress()} }>
<Text>{item.name}</Text>
</Pressable>
</Animated.View>
);
}
export default function App() {
const items = [
{ id: 1, name: 'name 1' },
{ id: 2, name: 'name 2' },
{ id: 3, name: 'name 3' },
{ id: 4, name: 'name 4' },
];
return (
<SafeAreaView style={styles.container}>
<FlatList
numColumns={4}
data={items}
renderItem={({item, index}) => <Item key={index} item={item} index={index} />}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});
Upvotes: 1