Skip to content

Instantly share code, notes, and snippets.

@ridgeO
Last active May 15, 2021 08:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ridgeO/b57bfc6faaf0fcbc7837d50ecfec2004 to your computer and use it in GitHub Desktop.
Save ridgeO/b57bfc6faaf0fcbc7837d50ecfec2004 to your computer and use it in GitHub Desktop.
Code snippets from RNCardStack application as featured in http://platypus.is/posts/7
# index.ios.js and index.android.js
import './components/App.js';
# components/App.js
'use strict';
import React, { Component } from 'react';
import {
AppRegistry,
Text,
View
} from 'react-native';
import Styles from './Styles.js';
export default class RNCardStack extends Component {
render() {
return (
<View style={Styles.container}>
<Text style={Styles.welcome}>
Welcome to React Native!
</Text>
</View>
);
}
}
AppRegistry.registerComponent('RNCardStack', () => RNCardStack);
# components/App.js
...
import Card from './Card.js';
...
return (
<View style={Styles.container}>
<Card/>
</View>
...
# components/Card.js
'use strict';
import React, { Component } from 'react';
import {
View,
Image,
Text
} from 'react-native';
import Styles from './Styles.js';
export default class Card extends Component {
render() {
return (
<View style={Styles.card}>
<Image style={Styles.cardImage}/>
<View style={Styles.cardText}>
<Text style={Styles.cardTextMain}>Name, Age</Text>
<Text style={Styles.cardTextSecondary}>Job Title and Employer</Text>
</View>
</View>
);
}
}
# components/Card.js
...
import {
PanResponder,
Animated,
View,
Image,
Text
} from 'react-native';
...
# components/Card.js
...
constructor(props) {
super(props);
this.state = {
pan: new Animated.ValueXY()
};
}
...
# components/Card.js
...
componentWillMount() {
this.panResponder = PanResponder.create({
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderGrant: (e, gestureState) => {},
onPanResponderMove: Animated.event([]),
onPanResponderRelease: (e, {vx, vy}) => {}
})
}
...
render() {
return (
<Animated.View {...this.panResponder.panHandlers}>
...
</Animated.View>
...
# component/Card.js
...
onPanResponderGrant: (e, gestureState) => {
this.state.pan.setValue({x: 0, y: 0});
},
onPanResponderMove: Animated.event([
null, {dx: this.state.pan.x, dy: this.state.pan.y}
]),
...
# component/Card.js
...
componentWillUnmount() {
this.state.pan.x.removeAllListeners();
this.state.pan.y.removeAllListeners();
}
...
# component/Card.js
...
getMainCardStyle() {
let {pan} = this.state;
return [
Styles.mainCard,
{transform: [{translateX: pan.x}, {translateY: pan.y}]}
];
}
...
render() {
return (
<Animated.View style={this.getMainCardStyle()} {...this.panResponder.panHandlers}>
...
# components/Card.js
...
onPanResponderRelease: (e, {vx, vy}) => {
Animated.spring(this.state.pan, {
toValue: 0,
}).start()
}
...
# components/Card.js
...
return [
Styles.mainCard,
{transform: [{translateX: pan.x}, {translateY: pan.y},
{rotate: pan.x.interpolate({inputRange: [-150, 0, 150], outputRange: ["-20deg", "0deg", "20deg"]})}]},
{opacity: pan.x.interpolate({inputRange: [-150, 0, 150], outputRange: [0.5, 1, 0.5]})}
];
}
...
# components/App.js
...
return (
<View style={Styles.container}>
<CardStack/>
</View>
...
# components/CardStack.js
'use strict';
import React, { Component } from 'react';
import { FlatList } from 'react-native';
import Styles from './Styles.js';
import Card from './Card.js';
export default class CardStack extends Component {
render() {
return (
<FlatList/>
);
}
}
# components/CardList.js
...
constructor(props) {
super(props);
this.state = {
users: [],
};
}
...
# components/App.js
...
componentWillMount() {
this.handleAdd();
}
async handleAdd() {
try {
let response = await fetch('https://randomuser.me/api');
let result = await response.json();
this.setState({
users: [result.results[0], ...this.state.users],
});
} catch (err) {
alert(JSON.stringify(err));
}
};
...
# components/CardStack.js
...
<FlatList
style={Styles.cardContainer}
contentContainerStyle={Styles.cardStack}
data={this.state.users}
renderItem={({item, index}) => (
<Card
{...item}
index={index}
/>
)}
keyExtractor={(item) => item.login.username}
scrollEnabled={false}
/>
...
# components/Card.js
...
render() {
let {picture, name, email} = this.props;
...
<Image source={{uri: picture.large}} style={Styles.cardImage}/>
<View style={Styles.cardText}>
<Text style={Styles.cardTextMain}>{name.first} {name.last}</Text>
<Text style={Styles.cardTextSecondary}>{email}</Text>
...
# components/Card.js
...
componentWillMount() {
for(let i = 0; i < 3; i++){
this.handleAdd();
}
}
...
# components/Card.js
...
getMainCardStyle() {
let {pan} = this.state;
return [
Styles.mainCard,
{position: 'absolute'},
{left: -175},
{top: -250},
...
# components/CardStack.js
...
handleRemove = (index) => {
let start = this.state.users.slice(0, index);
let end = this.state.users.slice(index + 1);
this.setState({
users: start.concat(end),
});
this.handleAdd();
};
...
# components/CardStack.js
...
<Card
{...item}
index={index}
onSwipe={this.handleRemove}
/>
...
# components/Card.js
...
onPanResponderRelease: (e, {vx, vy}) => {
if (this.state.pan.x._value < -150) {
this.props.onSwipe(this.props.index)
} else if (this.state.pan.x._value > 150) {
this.props.onSwipe(this.props.index)
} else {
Animated.spring(this.state.pan, {
toValue: 0,
}).start()
}
}
...
# components/Card.js
...
onPanResponderRelease: (e, {vx, vy}) => {
if (this.state.pan.x._value < -150) {
this.props.onSwipe(this.props.index)
} else if (this.state.pan.x._value > 150) {
this.props.onSwipe(this.props.index)
} else {
Animated.spring(this.state.pan, {
toValue: 0,
}).start()
}
}
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment