電通国際情報サービス、オープンイノベーションラボの比嘉康雄です。
今回は、Expoの公式チュートリアルをやっていきたいと思います。
- プロジェクトの作成
- Download assets
- Install dependencies
- アプリの実行
- コードの編集
- テキストの文字色の変更
- イメージの表示
- ImageViewerコンポーネント
- Buttonコンポーネント
- PhotoButtonコンポーネント
- 画像の選択
- まとめ
- 仲間募集
プロジェクトの作成
StickerSmashプロジェクトを作成しましょう。
npx create-expo-app StickerSmash && cd StickerSmash
Download assets
https://docs.expo.dev/static/images/tutorial/sticker-smash-assets.zip
をダウンロードしてから解凍し、StickerSmash/assetsに格納します。既存のファイルは置き換えてください。
Install dependencies
Webでも実行できるようにするために、必要なモジュールをインストールします。
npx expo install react-dom react-native-web @expo/webpack-config
アプリの実行
プロジェクトのディレクトリで、npx expo startを実行します。
wを押すと、Webアプリを試すことができます。
次のように表示されました。

コードの編集
プロジェクトのディレクトリで、code .を実行して、VS Codeを立ち上げます。
背景を#25292eに変更しましょう。
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#25292e",
alignItems: "center",
justifyContent: "center",
},
});
次のように表示されました。

テキストのデフォルトの文字色は黒なので、背景が黒っぽくなったことで、文字が見え辛くなってしまいました。
テキストの文字色の変更
Textタグのstyle属性で、文字の色を白に指定しましょう。
<Text style={{ color: "#fff" }}>
Open up App.js to start working on your app!
</Text>
次のように表示されました。

イメージの表示
イメージを表示しましょう。
Imageコンポーネントをインポートします。
import { StyleSheet, View, Image } from 'react-native';
次は、イメージパスの設定です。
const PlaceholderImage = require('./assets/images/background-image.png');
Imageタグを使う前に、スタイルシートの設定をしましょう。
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#25292e",
alignItems: "center",
},
imageContainer: {
flex: 1,
paddingTop: 58,
},
image: {
width: 320,
height: 440,
borderRadius: 18,
},
});
準備ができたので、Imageコンポーネントを使ってみましょう。
<View style={styles.imageContainer}>
<Image source={PlaceholderImage} style={styles.image} />
</View>
下記のように表示されました。

ImageViewerコンポーネント
先ほど作ったイメージ表示機能をコンポーネント化しましょう。
StickSmashディレクトリの中にcomponentsディレクトリを作成します。
.../StickerSmash$ mkdir components
VS CodeでImageViewer.jsを作成します。
code components/ImageViewer.js
下記のコードをImageViewer.jsに書き込みます。
import { StyleSheet, Image } from 'react-native';
export default function ImageViewer({ placeholderImageSource }) {
return (
<Image source={placeholderImageSource} style={styles.image} />
);
}
const styles = StyleSheet.create({
image: {
width: 320,
height: 440,
borderRadius: 18,
},
});
App.jsからImageViewer.jsを呼び出します。
import ImageViewer from './components/ImageViewer';
const PlaceholderImage = require('./assets/images/background-image.png');
export default function App() {
return (
<View style={styles.container}>
<View style={styles.imageContainer}>
<ImageViewer placeholderImageSource={PlaceholderImage} />
</View>
<StatusBar style="auto" />
</View>
);
}
見た目はもちろん以前と一緒です。
Buttonコンポーネント
これからボタンを2つ作りますが、その前に、Buttonコンポーネントを作ってそれを利用することにしましょう。
VS CodeでButton.jsを作成します。
code components/Button.js
下記のコードをButton.jsに書き込みます。
import { StyleSheet, View, Pressable, Text } from 'react-native';
export default function Button({ label }) {
return (
<View style={styles.buttonContainer}>
<Pressable style={styles.button} onPress={() => alert('You pressed a button.')}>
<Text style={styles.buttonLabel}>{label}</Text>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
buttonContainer: {
width: 320,
height: 68,
marginHorizontal: 20,
alignItems: 'center',
justifyContent: 'center',
padding: 3,
},
button: {
borderRadius: 10,
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
},
buttonLabel: {
color: '#fff',
fontSize: 16,
},
});
App.jsからButton.jsを呼び出します。
import Button from './components/Button';
<View style={styles.footerContainer}>
<Button label="Choose a photo" />
<Button label="Use this photo" />
</View>
const styles = StyleSheet.create({
// Styles that are unchanged from previous step are hidden for brevity.
footerContainer: {
flex: 1 / 3,
alignItems: 'center',
},
});
下記のように表示されました。

PhotoButtonコンポーネント
写真アイコンが表示されるボタンを作りましょう。@expo/vector-iconをインストールします。
npx expo install @expo/vector-icons
VS CodeでPhotoButton.jsを作成します。
code components/PhotoButton.js
下記のコードをPhotoButton.jsに書き込みます。
import { StyleSheet, View, Pressable, Text } from "react-native";
import FontAwesome from "@expo/vector-icons/FontAwesome";
export default function PhotoButton({ label }) {
return (
<View style={styles.buttonContainer}>
<Pressable
style={styles.button}
onPress={() => alert("You pressed a button.")}
>
<FontAwesome
name="picture-o"
size={18}
color="#25292e"
style={styles.buttonIcon}
/>
<Text style={[styles.buttonLabel, {}]}>{label}</Text>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
buttonContainer: {
width: 320,
height: 68,
marginHorizontal: 20,
alignItems: "center",
justifyContent: "center",
padding: 3,
borderWidth: 4,
borderColor: "#ffd33d",
borderRadius: 18,
},
button: {
borderRadius: 10,
width: "100%",
height: "100%",
alignItems: "center",
justifyContent: "center",
flexDirection: "row",
backgroundColor: "#fff",
},
buttonIcon: {
paddingRight: 8,
},
buttonLabel: {
color: "#25292e",
fontSize: 16,
},
});
下記のように表示されました。

画像の選択
画像を選択する機能を実装しましょう。expo-image-pickerをインストールします。
npx expo install expo-image-picker
App.jsでpickImageAsyncファンクションを実装しましょう。選択した画像は、result.assets[0].uriに入っています。
import * as ImagePicker from 'expo-image-picker';
const pickImageAsync = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
quality: 1,
});
if (!result.canceled) {
alert(result.assets[0].uri);
} else {
alert('You did not select any image.');
}
};
PhotoButtonでボタンを押したときの動作が定義できるように、onPress属性を追加しましょう。
export default function PhotoButton({ label, onPress }) {
return (
<View style={styles.buttonContainer}>
<Pressable
style={styles.button}
onPress={onPress}
>
<FontAwesome
name="picture-o"
size={18}
color="#25292e"
style={styles.buttonIcon}
/>
<Text style={styles.buttonLabel>{label}</Text>
</Pressable>
</View>
);
}
App.jsでPhotoButtonが押されたときに、pickImageAsyncファンクションを呼び出します。
<PhotoButton label="Choose a photo" onPress={pickImageAsync} />
ImageViewerで選択した画像を表示できるように、selectedImage属性を追加します。
export default function ImageViewer(
{ placeholderImageSource, selectedImage }) {
const imageSource = selectedImage ?
{ uri: selectedImage } :
placeholderImageSource;
return <Image source={imageSource} style={styles.image} />;
}
App.jsで、写真が選択されたら、ImageViewerに表示します。
import { useState } from "react";
const PlaceholderImage = require("./assets/images/background-image.png");
export default function App() {
const [selectedImage, setSelectedImage] = useState(null);
const pickImageAsync = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
allowsEditing: true,
quality: 1,
});
if (!result.canceled) {
setSelectedImage(result.assets[0].uri);
} else {
alert("You did not select any image.");
}
};
return (
<View style={styles.container}>
<View style={styles.imageContainer}>
<ImageViewer
placeholderImageSource={PlaceholderImage}
selectedImage={selectedImage}
/>
</View>
<View style={styles.footerContainer}>
<PhotoButton label="Choose a photo" onPress={pickImageAsync} />
<Button label="Use this photo" />
</View>
<StatusBar style="auto" />
</View>
);
}
下記のように表示されました。

切りが良いので、前編はここまでとします。
まとめ
Expoの公式チュートリアルは、難易度もちょうどいい感じで、実践的な力が身につくなと感じました。ただ、JavaScriptじゃなくTypeScriptにしてほしかったところです。
仲間募集
私たちは同じグループで共に働いていただける仲間を募集しています。
現在、以下のような職種を募集しています。



