Version 1.2

Build a scavenger hunt mobile app

Scavenger Hunt Screenshot

These instructions will walk you through the creation of a cross-platform smartphone app, in the form of a scavenger hunt that prompts visitors to find and check off artifacts on display.

The app will be based on the free, versatile React Native framework used by Facebook, Instagram, and other prominent companies. You will customize React Native's HTML-like tags and test-drive your new app on your own Android or iOS device.

Requirements

This workshop assumes you already know why a mobile app would appeal to young users. Although everyone is welcome to attend regardless of background, participants who want to make the app should have these ready:

Caveats

3 parts of React Native code


	// Here you import the components necessary to build the app.
	import * as React from 'react' ;
	...
	export default function App() {
	  return (
	    // Here you add tags corresponding to the visible parts of the app.
		<ScrollView>...
	  );
	}
	const styles = StyleSheet.create({
	  // Here you style the color, text, and other aspects of the look of the app.
	  container: {
		backgroundColor: 'cadetblue',
		...
	  }
	});
	

Customize the template in your browser

Expo makes it easy to write apps in your browser, which are called Snacks. Visit the Scavenger Hunt snack in your browser and edit the code in the left pane to see a preview of the result at right:


...
export default function App() {
  return (
    <ScrollView style={styles.container}>
      <View style={styles.titleContainer}>
	  	  <Text style={styles.title}>My Awesome Hats</Text>
      </View>

<Image
	style={styles.thumbnail}
	source={{
	  uri:
	  	  'https://example.com/grumpy_cat.jpg',
	}}
/>

  <Text
    style={styles.question}
    ref={(component) => (this.manetQuestion = component)}>
		❓Whose cat is this?
  </Text>
  <Text
    style={styles.caption}
    ref={(component) => (this.manetCaption = component)}>
		✅ It's mine!
  </Text>

question: {
  ...
  fontSize: 24,
  color: 'yellow',
  fontFamily: 'Marker Felt',
  ...
},

See the app on your device

Share your version

Troubleshooting

🙂 The good news is that you can't break anything on the web or your phone with Expo, so don't worry if you see the Red Screen of Death while editing the code. You may just not be done with your revision, or you could have made one of the following mistakes.

Proofread your code

Copy Image LocationGet an image URL

Fix disappearing code

If your app fails to load in the simulator or device

Totally stuck?

Template code for reference


	// V3.7 works in iPhone and Android simulator.
	import * as React from 'react';
	import {
	  Text,
	  View,
	  StyleSheet,
	  ScrollView,
	  Image,
	  TouchableOpacity,
	} from 'react-native';
	export default function App() {
	  return (
	    <ScrollView style={styles.container}>
	      <View style={styles.titleContainer}>
	        <Text style={styles.title}>Scavenger Hunt 3.7</Text>
	      </View>
	      <TouchableOpacity
	        onPress={() => {
	          this.manetQuestion.setNativeProps({ style: { opacity: 0 } });
	          this.manetCaption.setNativeProps({ style: { opacity: 1 } });
	        }}>
	        <View style={styles.card}>
	          <Image
	            style={styles.thumbnail}
	            source={{
	              uri:
	                'https://tutorials.nmdprojects.net/react_native_scavenger_hunt/related_files/manet_before_the_mirror.jpg',
	            }}
	          />
	          <Text
	            style={styles.question}
	            ref={(component) => (this.manetQuestion = component)}>
	            ❓Who painted Before the Mirror (1876), featuring a woman whose face
	            you can't see?
	          </Text>
	          <Text
	            style={styles.caption}
	            ref={(component) => (this.manetCaption = component)}>
	            ✅ Although not considered an Impressionist, Eduard Manet conveys
	            detail with vivid brushwork.
	          </Text>
	        </View>
	      </TouchableOpacity>
	      <TouchableOpacity
	        onPress={() => {
	          this.picassoQuestion.setNativeProps({ style: { opacity: 0 } });
	          this.picassoCaption.setNativeProps({ style: { opacity: 1 } });
	        }}>
	        <View style={styles.card}>
	          <Image
	            style={styles.thumbnail}
	            source={{
	              uri:
	                'https://tutorials.nmdprojects.net/react_native_scavenger_hunt/related_files/picasso_woman_with_yellow_hair.jpg',
	            }}
	          />
	          <Text
	            style={styles.question}
	            ref={(component) => (this.picassoQuestion = component)}>
	            ❓Who was the model for this portrait by one of the most famous
	            artists of all time?
	          </Text>
	          <Text
	            style={styles.caption}
	            ref={(component) => (this.picassoCaption = component)}>
	            ✅ Marie-Therese Walter posed for this 1931 work by Pablo Picasso
	            when she was 21 and he was 49.
	          </Text>
	        </View>
	      </TouchableOpacity>
	      <TouchableOpacity
	        onPress={() => {
	          this.bonnardQuestion.setNativeProps({ style: { opacity: 0 } });
	          this.bonnardCaption.setNativeProps({ style: { opacity: 1 } });
	        }}>
	        <View style={styles.card}>
	          <Image
	            style={styles.thumbnail}
	            source={{
	              uri:
	                'https://tutorials.nmdprojects.net/react_native_scavenger_hunt/related_files/bonnard_dining_room_on_the_garden.jpg',
	            }}
	          />
	          <Text
	            style={styles.question}
	            ref={(component) => (this.bonnardQuestion = component)}>
	            ❓What is hidden in a corner of this dining room painted by Fauvist
	            artist Pierre Bonnard?
	          </Text>
	          <Text
	            style={styles.caption}
	            ref={(component) => (this.bonnardCaption = component)}>
	            ✅ Dining Room on the Garden (1934-35) contains a hidden figure who
	            blends into the background.
	          </Text>
	        </View>
	      </TouchableOpacity>
	    </ScrollView>
	  );
	}
	const styles = StyleSheet.create({
	  container: {
	    flex: 1,
	    justifyContent: 'flex-start',
	    backgroundColor: 'cadetblue',
	    padding: 8,
	  },
	  titleContainer: {
	    display: 'flex',
	    alignItems: 'center',
	  },
	  title: {
	    fontWeight: 'bold',
	    color: 'teal',
	    fontSize: 24,
	    marginTop: 30,
	  },
	  card: {
	    display: 'flex',
	    flexDirection: 'row',
	    justifyContent: 'flex-start',
	    padding: 24,
	    backgroundColor: 'slategray',
	    marginTop: 20,
	    borderRadius: 20,
	  },
	  thumbnail: {
	    width: 100,
	    height: 100,
	  },
	  question: {
	    position: 'absolute',
	    left: 140,
	    top: 20,
	    fontSize: 18,
	    color: 'white',
	    width: '64%',
	  },
	  caption: {
	    position: 'absolute',
	    left: 140,
	    top: 20,
	    fontSize: 18,
	    color: 'paleturquoise',
	    width: '64%',
	    opacity: 0,
	  },
	});