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(() => ({
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?