Reputation: 1083
I'm facing this challenge, client want me to make a moving animation when click other item in a top nav bar, it will have animation that switch to another item: something like apple music, as video below: https://streamable.com/yg1j2j
But i have no idea where to start with this, please help, thank you a lots
Upvotes: 1
Views: 1937
Reputation: 9733
We can achieve this using the following setup.
View
that contains two children: A FlatList
that holds our items ("Products", "Stores", ...) and an Animated.View
which will represent our animated background color of the selected item.Animated.Value
which we will use to create a smooth movement of our Animated.View
on item selection.This solution is a little bit hacky since we explicitly use the knowledge that we have of the items in our list. There might be a better more general solution for this.
Here is a minimal working example and a snack where you can try out my solution.
const data = [
{
id: "1",
text: "Results",
},
{
id: "2",
text: "Products",
},
{
id: "3",
text: "Stores",
},
]
const [translateValue] = useState(new Animated.Value(0))
const [selected, setSelected] = useState(0)
const onPress = React.useCallback(
(index) => {
setSelected(index)
Animated.spring(translateValue, {
toValue: index * 100,
velocity: 5,
useNativeDriver: true,
}).start()
},
[translateValue, setSelected]
)
return (
<View style={{ flexDirection: "row", marginTop: 100 }}>
<Animated.View
style={[
{
position: "absolute",
backgroundColor: "black",
top: -5,
right: 0,
bottom: 0,
left: 15,
width: 70,
height: 30,
borderRadius: 12,
transform: [{ translateX: translateValue }],
},
]}
/>
<FlatList
data={data}
horizontal={true}
scrollEnabled={false}
renderItem={({ item, index }) => {
return (
<TouchableOpacity onPress={() => onPress(index)}>
<View style={{ width: 100, borderRadius: 10 }}>
<Text style={[{ textAlign: "center" }, index === selected ? { color: "white" } : { color: "black" }]}>
{item.text}
</Text>
</View>
</TouchableOpacity>
)
}}
keyExtractor={(item) => item.id}
/>
</View>
)
Upvotes: 2