|
import React from 'react'; |
|
import {Image, StyleSheet, TouchableOpacity, Dimensions, View, Animated, PanResponder, Text} from 'react-native'; |
|
import { Constants, BlurView } from 'expo'; |
|
|
|
class ReachNavigationDemo extends React.Component { |
|
state = { isClosed: true, scroll: new Animated.Value(0) } |
|
position = 0; |
|
panResponder = PanResponder.create({ |
|
onMoveShouldSetResponderCapture: () => true, |
|
onMoveShouldSetPanResponderCapture: (_, { dy }) => Math.abs(dy) > 0.5, |
|
onPanResponderMove: (_, {dy}) => { |
|
this.state.scroll.setValue(this.position + dy) |
|
}, |
|
onPanResponderRelease: (e, { vy }) => { |
|
this.setOpenState(vy > 0) |
|
} |
|
}) |
|
|
|
setOpenState = isClosed => { |
|
if (isClosed !== this.state.isClosed && this.props.onOpenStateChange) { |
|
setTimeout(this.props.onOpenStateChange) |
|
} |
|
|
|
this.position = isClosed ? 0 : -500; |
|
this.setState({isClosed}) |
|
Animated.timing(this.state.scroll, { |
|
toValue: this.position, |
|
duration: 100, |
|
}).start() |
|
} |
|
|
|
toggle = () => { |
|
const state = JSON.parse(JSON.stringify(this.state.scroll)) |
|
this.setOpenState(state < 0) |
|
} |
|
|
|
isClosed = () => { |
|
return this.state.isClosed |
|
} |
|
|
|
render() { |
|
const {height: windowHeight, width: windowWidth} = Dimensions.get('window') |
|
const height = windowHeight - 75 |
|
const interpolateScroll = outputRange => this.state.scroll.interpolate({ |
|
outputRange, |
|
inputRange: [-height, 0, 100], |
|
extrapolate: "clamp", |
|
}) |
|
const maybeTouchable = x => this.state.isClosed ? ( |
|
<TouchableOpacity |
|
onPress={this.isClosed() ? this.toggle : undefined} |
|
style={{flex: 1}} |
|
> |
|
{x} |
|
</TouchableOpacity> |
|
) : x; |
|
|
|
// interpolation! |
|
const width = interpolateScroll([windowWidth, windowWidth - 50, windowWidth - 50]) |
|
const translateY = interpolateScroll([50, height, height + 10]); |
|
const translateX = interpolateScroll([0, 25, 25]); |
|
const shadowOpacity = interpolateScroll([0.7, 0.2, 0.2]) |
|
const shadowRadius = interpolateScroll([10, 2, 2]) |
|
|
|
return ( |
|
<Animated.View |
|
{...this.panResponder.panHandlers} |
|
style={{ |
|
position: 'absolute', |
|
top: 0, |
|
backgroundColor: '#f7f7f7', |
|
left: 0, |
|
shadowOpacity, |
|
shadowRadius, |
|
height, |
|
width, |
|
transform: [{ translateX }, { translateY }] |
|
}} |
|
> |
|
{maybeTouchable( |
|
<View flex={1}> |
|
<Text style={{fontSize: 15, fontWeight: 'bold', letterSpacing: 3, padding: 8, color: 'rgba(0,0,0,0.6)'}}>YOU ARE A WIZARD HARRY</Text> |
|
<Text style={{padding: 8}}>This is not negotiable</Text> |
|
</View> |
|
)} |
|
</Animated.View> |
|
); |
|
} |
|
} |
|
|
|
const MapMock = ({style}) => ( |
|
<Image |
|
source={{uri: 'https://i.stack.imgur.com/baRy9.png'}} |
|
style={style} |
|
/> |
|
); |
|
|
|
export default class App extends React.Component { |
|
render() { |
|
return ( |
|
<View flex={1}> |
|
<MapMock style={StyleSheet.absoluteFill} /> |
|
<BlurView |
|
tint="light" |
|
intensity={80} |
|
style={{height: Constants.statusBarHeight}} |
|
/> |
|
<ReachNavigationDemo /> |
|
</View> |
|
); |
|
} |
|
} |