LocationPin
In this section, we will focus on building the pinpointing to the center of the map to visually confirm the pickup location. This pin also contains a button, which can be used to trigger a pickup request:
/** * src/components/LocationPin.js ** */ import React from 'react'; import { View, Text, Dimensions, TouchableOpacity, StyleSheet, } from 'react-native'; const { height, width } = Dimensions.get('window'); export default class LocationPin extends React.Component { render() { return ( <View style={styles.container}> <View style={styles.banner}> <Text style={styles.bannerText}>SET PICKUP LOCATION</Text> <TouchableOpacity style={styles.bannerButton} onPress={this.props.onPress} > <Text style={styles.bannerButtonText}>{'>'}</Text> </TouchableOpacity> </View> <View style={styles.bannerPole} /> </View> ); } } const styles = StyleSheet.create({ container: { position: 'absolute', top: height / 2 - 60, left: width / 2 - 120, }, banner: { flexDirection: 'row', alignSelf: 'center', justifyContent: 'center', borderRadius: 20, backgroundColor: '#333', padding: 10, paddingBottom: 10, shadowColor: '#000000', shadowOffset: { width: 0, height: 3, }, shadowRadius: 5, shadowOpacity: 1.0, }, bannerText: { alignSelf: 'center', color: 'white', marginRight: 10, marginLeft: 10, fontSize: 18, }, bannerButton: { borderWidth: 1, borderColor: '#ccc', width: 26, height: 26, borderRadius: 13, }, bannerButtonText: { color: 'white', textAlign: 'center', backgroundColor: 'transparent', fontSize: 18, }, bannerPole: { backgroundColor: '#333', width: 3, height: 30, alignSelf: 'center', }, });
This component is again very light in terms of functionality, but has a lot of custom style. Let's dive into some of the style details.
flexDirection
By default, React Native and Flexbox stack elements vertically:
For the banner in our pin, we want to stack every element horizontally after each other as follows:
This can be achieved by adding the following styles to the containing element flexDirection: 'row'
. The other valid options for flexDirection
are:
row-reverse
column
(default)column-reverse
Dimensions
One of the first lines of code in this component extracts the height and the width from the device into two variables:
const {height, width} = Dimensions.get('window');
Obtaining the height and width of the device enables us developers to absolute position some elements being confident they will show properly aligned. For example, we want the banner of our pin to be aligned in the center of the screen, so it points to the center of the map. We can do this by adding {top: (height/2), left: (width/2)}
to the banner
style in our style sheet. Of book, that would align the upper-left corner, so we need to subtract half the size of the banner to each property to ensure it gets centered in the middle of the element. This trick can be used whenever we need to align an element that is not relative to any other in the components tree although it is recommended to use relative positioning when possible.
Shadows
Let's set focus on our banner's style, specifically on the shadows
properties:
banner: { ... shadowColor: '#000000', shadowOffset: { width: 0, height: 3 }, shadowRadius: 5, shadowOpacity: 1.0 }
In order to add a shadow to a component, we need to add four properties:
shadowColor
: This adds the hexadecimal or RGBA value of the color we want for our componentshadowOffset
: This shows how far we want our shadow to be castedshadowRadius
: This shows the value of the radius in the corner of our shadowshadowOpacity
: This shows how dark we want our shadow to be
That's it for our LocationPin
component.