import React, { Component } from 'react';
import {
View,
Animated,
PanResponder,
ActivityIndicator,
StyleSheet
} from 'react-native';
import {Constants} from 'expo'
export const withSnap = ({
startValue = 0,
endValue = 0,
duration = 200
}) => WrappedComponent => {
return class SnapHeader extends Component {
animatedValue = new Animated.Value(startValue);
componentWillMount() {
this._panResponder = PanResponder.create({
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderMove: (e, gestureState) => {
if (gestureState.dy < 0 && Math.abs(gestureState.dy) > 30) {
Animated.timing(this.animatedValue, {
duration,
toValue: endValue,
}).start();
} else if (gestureState.dy > 0 && Math.abs(gestureState.dy) > 30) {
Animated.timing(this.animatedValue, {
duration,
toValue: startValue,
}).start();
}
},
});
}
render() {
return (
<View>
<ActivityIndicator size="small" />
<WrappedComponent
{...this.props}
snap={{
panHandlers: this._panResponder.panHandlers,
animatedValue: this.animatedValue,
}}
/>
</View>
);
}
};
};
export const Header = props =>
<View {...props.snap.panHandlers}>
<Animated.View
style={{
backgroundColor: 'black',
height: props.snap.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [500, 50],
extrapolate: 'clamp',
}),
justifyContent: 'center',
alignItems: 'center',
position: 'relative',
}}
>
<Animated.Text
style={{
fontSize: props.snap.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [48, 24],
extrapolate: 'clamp',
}),
fontWeight: 'bold',
color: 'white',
textAlign: 'center',
}}
>
OH SNAP!
</Animated.Text>
</Animated.View>
</View>;
const HeaderWithSnap = withSnap({ startValue: 0, endValue: 1, duration: 200 })(Header);
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<HeaderWithSnap />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'stretch',
justifyContent: 'flex-start',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
cool!