Skip to content
Permalink
Browse files

add code for panning animation

- disable scroll while panning
- remove animated header because its getting in the way
  • Loading branch information...
anchetaWern committed Jun 27, 2018
1 parent b5418e2 commit b0d9ccb7d3cf79feccaa278982d01d12c7399c05
Showing with 251 additions and 64 deletions.
  1. +119 −41 src/components/Card.js
  2. +14 −13 src/components/CardList.js
  3. +37 −0 src/components/DropArea.js
  4. +74 −9 src/screens/Main.js
  5. +7 −1 src/settings/layout.js
@@ -5,49 +5,129 @@ import {
Image,
TouchableWithoutFeedback,
Animated,
Easing
Easing,
PanResponder
} from "react-native";
import IconButton from "./IconButton";

const Card = ({
item,
cardAction,
viewAction,
bookmarkAction,
shareAction
}) => {
let scaleValue = new Animated.Value(0);
type Props = {};
export default class Card extends Component<Props> {
constructor(props) {
super(props);

const cardScale = scaleValue.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [1, 1.1, 1.2]
});
this.pan = new Animated.ValueXY();
this.scaleValue = new Animated.Value(0);
this.opacityValue = new Animated.Value(2);

let transformStyle = { ...styles.card, transform: [{ scale: cardScale }] };
this.cardScale = this.scaleValue.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [1, 0.5, 1]
});

return (
<TouchableWithoutFeedback
onPressIn={() => {
scaleValue.setValue(0);
Animated.timing(scaleValue, {
toValue: 1,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
}).start();
this.cardOpacity = this.opacityValue.interpolate({
inputRange: [0, 1, 2],
outputRange: [0, 0.5, 1]
});
}

componentWillMount() {
const {
item,
toggleDropArea,
isDropArea,
targetDropArea,
removePokemon
} = this.props;

this._val = { x: 0, y: 0 };
this.pan.addListener(value => (this._val = value));

this.panResponder = PanResponder.create({
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onPanResponderGrant: (e, gestureState) => {
Animated.parallel([
Animated.timing(this.scaleValue, {
toValue: 0.5,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
}),
Animated.timing(this.opacityValue, {
toValue: 1,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
})
]).start();

this.pan.setValue({ x: 0, y: 0 });
toggleDropArea(true, item);
},
onPanResponderMove: (e, gesture) => {
Animated.event([null, { dx: this.pan.x, dy: this.pan.y }])(e, gesture);
if (isDropArea(gesture)) {
targetDropArea(true);
} else {
targetDropArea(false);
}
},
onPanResponderRelease: (e, gesture) => {
toggleDropArea(false, item);

if (isDropArea(gesture)) {
Animated.timing(this.opacityValue, {
toValue: 0,
duration: 500,
useNativeDriver: true
}).start(() => {});

removePokemon(item);
} else {
Animated.parallel([
Animated.timing(this.scaleValue, {
toValue: 1,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
}),
Animated.timing(this.opacityValue, {
toValue: 2,
duration: 250,
easing: Easing.linear,
useNativeDriver: true
}),
Animated.spring(this.pan, {
toValue: { x: 0, y: 0 },
friction: 5,
useNativeDriver: true
})
]).start();
}
}
});
}

render() {
const {
item,
cardAction,
viewAction,
bookmarkAction,
shareAction
} = this.props;

let [translateX, translateY] = [this.pan.x, this.pan.y];

let transformStyle = {
...styles.card,
opacity: item.isVisible ? this.cardOpacity : 0,
transform: [{ translateX }, { translateY }, { scale: this.cardScale }]
};

cardAction();
}}
onPressOut={() => {
Animated.timing(scaleValue, {
toValue: 0,
duration: 100,
easing: Easing.linear,
useNativeDriver: true
}).start();
}}
>
<Animated.View style={transformStyle}>
return (
<Animated.View style={transformStyle} {...this.panResponder.panHandlers}>
<Image
source={item.pic}
style={styles.thumbnail}
@@ -72,9 +152,9 @@ const Card = ({
/>
</View>
</Animated.View>
</TouchableWithoutFeedback>
);
};
);
}
}

const styles = {
card: {
@@ -100,5 +180,3 @@ const styles = {
justifyContent: "space-between"
}
};

export default Card;
@@ -1,6 +1,7 @@
import React from "react";
import { ScrollView, View, FlatList, Animated, Platform } from "react-native";
import Card from "./Card";

import { HEADER_MAX_HEIGHT } from "../settings/layout";

const CardList = ({
@@ -9,22 +10,18 @@ const CardList = ({
viewAction,
bookmarkAction,
shareAction,
onScroll
onScroll,
scrollEnabled,
toggleDropArea,
isDropArea,
targetDropArea,
removePokemon
}) => {
return (
<Animated.ScrollView
style={styles.scroll}
scrollEventThrottle={1}
onScroll={onScroll}
contentInset={{
top: HEADER_MAX_HEIGHT
}}
contentOffset={{
y: -HEADER_MAX_HEIGHT
}}
>
<ScrollView scrollEnabled={scrollEnabled}>
<View style={[styles.scroll_container]}>
<FlatList
scrollEnabled={false}
data={data}
renderItem={({ item }) => (
<Card
@@ -33,13 +30,17 @@ const CardList = ({
viewAction={viewAction}
bookmarkAction={bookmarkAction}
shareAction={shareAction}
toggleDropArea={toggleDropArea}
isDropArea={isDropArea}
targetDropArea={targetDropArea}
removePokemon={removePokemon}
/>
)}
keyExtractor={item => item.id}
numColumns={2}
/>
</View>
</Animated.ScrollView>
</ScrollView>
);
};

@@ -0,0 +1,37 @@
import React, { Component } from "react";
import { View, Text, Dimensions } from "react-native";

const { height, width } = Dimensions.get("window");

const DropArea = ({ dropAreaIsVisible, setDropAreaLayout, isTargeted }) => {
const right = dropAreaIsVisible ? 20 : -200;
const color = isTargeted ? "#5fba7d" : "#333";
return (
<View
style={[styles.dropArea, { right }, { borderColor: color }]}
onLayout={setDropAreaLayout}
>
<Text style={[styles.dropAreaText, { color }]}>Drop here</Text>
</View>
);
};

const styles = {
dropArea: {
position: "absolute",
top: 20,
right: 20,
width: 100,
height: 100,
backgroundColor: "#eaeaea",
borderWidth: 3,
borderStyle: "dashed",
alignItems: "center",
justifyContent: "center"
},
dropAreaText: {
fontSize: 15
}
};

export default DropArea;
Oops, something went wrong.

0 comments on commit b0d9ccb

Please sign in to comment.
You can’t perform that action at this time.