Skip to content

Instantly share code, notes, and snippets.

@kmagiera
Created April 21, 2017 08:10
Show Gist options
  • Save kmagiera/710460dac3ba722bb6a8d552c343b44a to your computer and use it in GitHub Desktop.
Save kmagiera/710460dac3ba722bb6a8d552c343b44a to your computer and use it in GitHub Desktop.
import React, { Component } from 'react'
import { View, Image, StyleSheet, ScrollView, Text, Animated, StatusBar, PixelRatio } from 'react-native'
import Icon from 'react-native-vector-icons/MaterialIcons';
import MapView from 'react-native-maps';
const AMSTERDAM = {
latitude: 52.3702,
longitude: 4.8952,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}
const OFFSET = 450
class Maps extends Component {
render() {
return (
<View style={{flex: 1}}>
<MapView style={{flex: 1}} initialRegion={AMSTERDAM}/>
<Drawer />
</View>
)
}
}
class Drawer extends Component {
constructor(props) {
super(props)
this.state = {
expanded: false,
}
}
handleEndDrag = (e) => {
const targetY = e.nativeEvent.targetContentOffset.y
if (targetY < OFFSET) {
const snap = targetY < OFFSET / 3 ? 0 : OFFSET
this.refs["Scroll"].scrollTo({ y: snap })
}
}
handleBeginDrag = (e) => {
this.setState({ expanded: true })
}
handleAnimationEnd = (e) => {
const scrollY = e.nativeEvent.contentOffset.y
this.setState({ expanded: scrollY > 0 })
}
render() {
return (
<View style={[styles.container, { overflow: this.state.expanded ? 'visible' : 'hidden' }]}>
<ScrollView
style={styles.full}
stickyHeaderIndices={[1]}
showsVerticalScrollIndicator={false}
contentInset={{bottom: -255}}
ref="Scroll"
onScrollEndDrag={this.handleEndDrag}
onScrollBeginDrag={this.handleBeginDrag}
onMomentumScrollEnd={this.handleAnimationEnd}
>
<View style={styles.placeholder} />
<View style={styles.header}>
<View style={styles.handle} />
<Text style={styles.headerText}>Sticky header (pull here)</Text>
</View>
<Row icon="event-seat" text="Go watch a movie" color="#3949ab"/>
<Row icon="euro-symbol" text="Find some ca$$h" color="#00695c"/>
<Row icon="rowing" text="Random guy with a paddle" color="#827717"/>
<Row icon="radio" text="Very old radio" color="#6d4c41"/>
<Row icon="airplanemode-active" text="Fly away" color="#424242"/>
<Row icon="usb" text="Buy some USBs" color="#546e7a"/>
<Row icon="explore" text="Maybe use internet explorer" color="#e53935"/>
<Row icon="watch" text="Charge your watch..." color="#ff8f00"/>
<Row icon="wb-sunny" text="Good weather!" color="#1b5e20"/>
<Row icon="local-hospital" text="Need help?" color="#ad1457"/>
<Row icon="restaurant" text="Some fancy restaurant" color="#6a1b9a"/>
<Row icon="directions-bike" text="Get on a bike" color="#c0ca33"/>
<View style={styles.white}/>
</ScrollView>
</View>
)
}
}
const Row = ({icon, text, color}) => (
<View style={styles.row}>
<View style={[styles.rowIconContainer, {backgroundColor: color}]}>
<Icon name={icon} size={20} color="white" />
</View>
<Text style={styles.rowText}>{text}</Text>
</View>
)
const styles = StyleSheet.create({
container: {
position: 'absolute',
left: 0,
right: 0,
top: 40 + OFFSET,
bottom: 0,
},
full: {
marginTop: -OFFSET,
flex: 1,
},
header: {
backgroundColor: 'white',
height: 62,
borderTopWidth: 1 / PixelRatio.get(),
borderBottomWidth: 1 / PixelRatio.get(),
borderColor: '#8C99A5',
alignItems: 'center',
},
handle: {
width: 40,
height: 8,
borderRadius: 4,
backgroundColor: '#8C99A5',
margin: 4,
},
placeholder: {
height: OFFSET,
},
headerText: {
flex: 1,
fontSize: 22,
},
row: {
height: 60,
flex: 1,
flexDirection: 'row',
alignItems: 'center',
backgroundColor: 'white',
borderBottomWidth: 1 / PixelRatio.get(),
borderColor: '#8C99A5',
},
rowIconContainer: {
margin: 10,
width: 30,
height: 30,
borderRadius: 15,
alignItems: 'center',
justifyContent: 'center',
overflow: 'hidden',
},
rowText: {
fontSize: 18,
},
white: {
height: 255,
backgroundColor: 'white',
},
})
export default Maps
@kmagiera
Copy link
Author

kmagiera commented May 9, 2017

@ferrannp is this on iOS or android? I think the targetContentOffset may not be available on android in which case you may need to find another workaround.

As for the content behind being clickable this example should provide that. It works by changing the container size in which the scollview is placed (this.state.expanded is responsible for that)

Sorry for late response one again

@ferrannp
Copy link

@kmagiera yup Android, also the content behind is clickable on iOS but not on Android... So it looks like that getting this on Android https://material.io/guidelines/components/bottom-sheets.html#bottom-sheets-usage it is very tricky...

@j1mie
Copy link

j1mie commented Jul 29, 2018

Hey @kmagiera - running into a similar issue with Android as above. Any pointers would be much appreciated!

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