Skip to content

Instantly share code, notes, and snippets.

@wcandillon
Created September 3, 2018 09:28
Show Gist options
  • Save wcandillon/288e994cda3216d1dbef9482a9322804 to your computer and use it in GitHub Desktop.
Save wcandillon/288e994cda3216d1dbef9482a9322804 to your computer and use it in GitHub Desktop.
React Native Apple Wallet Animation
import React from "react";
import {
StyleSheet,
Text,
View,
ScrollView,
Animated,
SafeAreaView,
Dimensions
} from "react-native";
const cardHeight = 250;
const cardTitle = 45;
const cardPadding = 10;
const { height } = Dimensions.get("window");
const cards = [
{
name: "Shot",
color: "#a9d0b6",
price: "30 CHF"
},
{
name: "Juice",
color: "#e9bbd1",
price: "64 CHF"
},
{
name: "Mighty Juice",
color: "#eba65c",
price: "80 CHF"
},
{
name: "Sandwich",
color: "#95c3e4",
price: "85 CHF"
},
{
name: "Combi",
color: "#1c1c1c",
price: "145 CHF"
},
{
name: "Signature",
color: "#a390bc",
price: "92 CHF"
},
{
name: "Coffee",
color: "#fef2a0",
price: "47 CHF"
}
];
export default class App extends React.Component {
state = {
y: new Animated.Value(0)
};
render() {
const { y } = this.state;
return (
<SafeAreaView style={styles.root}>
<View style={styles.container}>
<View style={StyleSheet.absoluteFill}>
{cards.map((card, i) => {
const inputRange = [-cardHeight, 0];
const outputRange = [
cardHeight * i,
(cardHeight - cardTitle) * -i
];
if (i > 0) {
inputRange.push(cardPadding * i);
outputRange.push((cardHeight - cardPadding) * -i);
}
const translateY = y.interpolate({
inputRange,
outputRange,
extrapolateRight: "clamp"
});
return (
<Animated.View
key={card.name}
style={{ transform: [{ translateY }] }}
>
<View
style={[styles.card, { backgroundColor: card.color }]}
/>
</Animated.View>
);
})}
</View>
<Animated.ScrollView
scrollEventThrottle={16}
contentContainerStyle={styles.content}
showsVerticalScrollIndicator={false}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: { y }
}
}
],
{ useNativeDriver: true }
)}
/>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
root: {
flex: 1,
margin: 16
},
container: {
flex: 1
},
content: {
height: height * 2
},
card: {
height: cardHeight,
borderRadius: 10
}
});
@bkalmuk
Copy link

bkalmuk commented Nov 25, 2021

how can i make the items inside the card clickable, the TouchableOpacity is not working inside the card

I did like this and it worked

<SafeAreaView style={styles.root}>
        <View style={styles.container}>
          <Animated.ScrollView
            scrollEventThrottle={16}
            contentContainerStyle={styles.content}
            showsVerticalScrollIndicator={false}
            onScroll={Animated.event(
              [
                {
                  nativeEvent: {
                    contentOffset: { y }
                  }
                }
              ],
              { useNativeDriver: true }
            )}
          >
<View style={StyleSheet.absoluteFill}>
            {cards.map((card, i) => {
              const inputRange = [-cardHeight, 0];
              const outputRange = [
                cardHeight * i,
                (cardHeight - cardTitle) * -i
              ];
              if (i > 0) {
                inputRange.push(cardPadding * i);
                outputRange.push((cardHeight - cardPadding) * -i);
              }
              const translateY = y.interpolate({
                inputRange,
                outputRange,
                extrapolateRight: "clamp"
              });
              return (
                <Animated.View
                  key={card.name}
                  style={{ transform: [{ translateY }] }}
                >
                  <View
                    style={[styles.card, { backgroundColor: card.color }]}
                  />
                </Animated.View>
              );
            })}
          </View>
           </ Animated.ScrollView>
        </View>
      </SafeAreaView>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment