Phone
Build a native app in twenty minutes

May 2017

In this post, we're going to jump straight into React Native. We'll build an app that has a bunch of pictures and a map. These pictures are of different cities, and you can scroll through them; when you click an image, the map will update with its location.

Let's get into it!


Getting started

Rather than updating our machine with the React Native [RN] build tools etc. we can just use Snack. It's like CodePen, but for RN.

Click here to open up the Snack IDE. Follow their links to download the app to your phone.

Once you've got the Expo app on your phone, use it to scan the QR code in the Snack IDE, and you'll have their 'Hello, World' app running on your phone.

Modules

We'll be using extra modules in our app and it's easiest if you just import them all now. Replace the import statements with this:

import React, { Component } from 'react';
import { Text, View, StyleSheet, ScrollView, Image, Dimensions, TouchableOpacity, Button, Linking } from 'react-native';
import { Constants, MapView, Accelerometer } from 'expo';

Adding the images

Delete the <Text> component (and everything inside it) from your code and replace it with an <Image> component:

<Image 
  source={{ uri: 'https://s3-eu-west-1.amazonaws.com/work.ninjapixel.io/meetup-may-2017/london.jpg' }}
  style={{ width: 400, height: 200 }}/>

Your app will update, and you'll see a picture of the London Eye.

In RN you have to be upfront with image dimensions. 400 dips x 200 dips works fine on my phone, but it would look much nicer if we had an edge-to-edge image. We can easily grab the dimensions of the screen, and use these to display an appropriately sized image:

const { width, height } = Dimensions.get('window');
<Image
  source={{ uri: 'https://s3-eu-west-1.amazonaws.com/work.ninjapixel.io/meetup-may-2017/london.jpg' }}
  style={{ width: width, height: height*0.3 }}
/>

Rather than repeating the style in every image that we specify, we can set its properties in the styles const. So, let's add some more images and make use of a shared styles property:

The ScrollView

The app is shaping up nicely and in this next step, we will put the images into a ScrollView and also refactor the code, to make the boilerplate image rendering more succinct.

All you need to do is wrap the <Image> components with a <ScrollView horizontal> and you'll have some lovely, native horizontal scrolling.

As for the code refactor, we'll create an array of objects that contain a URL for the image (along with coordinates - we will use these later). The array will then be mapped to <Image> components. This is a standard pattern in RN that you will frequently see.

Implementing these changes, our code now looks like this (also note, that I have bumped up the height of the images)

Savour the native ScrollView! We've used the platform's native scroll element and got the physics engine that is associated with it for free. Imagine trying to get the same feel in a web or hybrid app.

The map

Using the Snack IDE it's really easy to drop a native map component into our app. Simply search down the list of components on the right side of your screen and drag the 'MapView' into your code, inserting it just after the <ScrollView>.

This will have inserted the <MapView> component, along with a new state for the map and a _handleMapRegionChange function, which updates the state when the map is panned.

Snack will have hard coded a style to the <MapView> component when you dropped it in. Let's make it use our styles const instead, and while we're at it, let's utilise flexbox to make sure that our map takes up half the screen (note that I have wrapped a <View> around the <ScrollView>, to enable this):

Interaction

In the final step of this post, we will add a handler to our images, so that when they are pressed the map will update to the relevant location.

We will use RN's TouchableOpacity component and hook into the onPress event. We simple update the mapRegion state and, because it is a prop of the MapView, the map will update with the corrinates of our picture. Here's our change:

renderImages = ()=>{            
  const onPressButton= ({lat, lng})=>{
    const mapRegion= { latitude: lat, longitude: lng, latitudeDelta: 0.0, longitudeDelta: 0.0 };
    this.setState({mapRegion:mapRegion});
  };
  
  return images.map((d,i)=>(
    <TouchableOpacity onPress={()=>onPressButton(d)}>
    <Image 
    key={i} source={{ uri: d.url }}
      style={styles.image}
    />
    </TouchableOpacity>
    ));
};

Here's the complete file:

Summary

That concludes the tutorial; hopefully you found it as much fun as I did.

Stay tuned for my next post where we'll be getting extra schwifty, by hooking into the device's accelerometer and auto-scrolling images as you tilt your phone 📲

Please enable JavaScript to view the comments powered by Disqus.