Expoメモ
プロジェクト作成
npx create-expo-app StickerSmash --template blank && cd StickerSmash
必要なAssetをassetフォルダに
必要なライブラリをインストール
npx expo install react-dom react-native-web @expo/metro-runtime
起動
npx expo start
QRコードをiPhoneカメラで読み込んでExpo Goを接続する
Expo Goのデバッグメニューは画面のどこでもいいから三本指で長押し
基本的にReactと同じ記法 styleはこんな感じでjsファイル中に記載するのが一般的?
<View>で構造を作り、flexで同じ階層中のflexの合計値の割合で大きさが変わる
例: flex:1 flex:2 flex:3 だとすると画面の1/6, 2/6, 3/6となる
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, Image } from 'react-native';
import PlaceholderImage from './assets/images/background-image.png';
import ImageViewer from './components/ImageViewer';
export default App = () => {
return (
<View style={styles.container}>
<View style={styles.imageContainer}>
<ImageViewer placeholderImageSource={PlaceholderImage} />
</View>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#25292e',
alignItems: 'center',
},
imageContainer: {
flex: 1,
paddingTop: 58,
}
});
別のライブラリ追加をするときはこんな感じ
ベクターアイコンのライブラリ
npx expo install @expo/vector-icons
再利用可能なボタンがこんな感じ
import { StyleSheet, View, Pressable, Text } from 'react-native';
import { FontAwesome } from '@expo/vector-icons';
export default Button = ({ label, theme }) => {
if (theme === "primary") {
return (
<View style={[styles.buttonContainer, { borderWidth: 4, borderColor: "#ffd33d", borderRadius: 18 }]}>
<Pressable
style={[styles.button, { backgroundColor: "#fff" }]}
onPress={() => alert('You pressed a button.')}
>
<FontAwesome
name="picture-o"
size={18}
color="#25292e"
style={styles.buttonIcon}
/>
<Text style={[styles.buttonLabel, { color: "#25292e" }]}>{label}</Text>
</Pressable>
</View>
);
}
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',
},
buttonIcon: {
paddingRight: 8,
},
buttonLabel: {
color: '#fff',
fontSize: 16,
},
});
基本的にReactと変わらない
<Modal>はぴょんと出てくるパネルのこと
import { Modal, View, Text, Pressable, StyleSheet } from 'react-native';
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
export default EmojiPicker = ({ isVisible, children, onClose }) => {
return (
<Modal animationType="slide" transparent={true} visible={isVisible}>
<View style={styles.modalContent}>
<View style={styles.titleContainer}>
<Text style={styles.title}>Choose a sticker</Text>
<Pressable onPress={onClose}>
<MaterialIcons name="close" color="#fff" size={22} />
</Pressable>
</View>
{children}
</View>
</Modal>
);
}
const styles = StyleSheet.create({
modalContent: {
height: '25%',
width: '100%',
backgroundColor: '#25292e',
borderTopRightRadius: 18,
borderTopLeftRadius: 18,
position: 'absolute',
bottom: 0,
},
titleContainer: {
height: '16%',
backgroundColor: '#464C55',
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
paddingHorizontal: 20,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
title: {
color: '#fff',
fontSize: 16,
},
pickerContainer: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 50,
paddingVertical: 20,
},
});
ジェスチャーの追加
npx expo install react-native-gesture-handler react-native-reanimated
ジェスチャーの管理コンポーネントでラップする
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
export default EmojiSticker = ({ imageSize, stickerSource }) => {
const scaleImage = useSharedValue(imageSize);
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const doubleTap = Gesture.Tap()
.numberOfTaps(2)
.onStart(() => {
if (scaleImage.value !== imageSize * 2) {
scaleImage.value = scaleImage.value * 2;
}
});
const drag = Gesture.Pan()
.onChange((event) => {
translateX.value += event.changeX;
translateY.value += event.changeY;
});
const imageStyle = useAnimatedStyle(() => {
return {
width: withSpring(scaleImage.value),
height: withSpring(scaleImage.value),
};
});
const containerStyle = useAnimatedStyle(() => {
return {
transform: [
{ translateX: translateX.value },
{ translateY: translateY.value },
],
};
});
return (
<GestureDetector gesture={drag}>
<Animated.View style={[containerStyle, { top: -350 }]}>
<GestureDetector gesture={doubleTap}>
<Animated.Image
source={stickerSource}
resizeMode="contain"
style={[imageStyle, { width: imageSize, height: imageSize }]}
/>
</GestureDetector>
</Animated.View>
</GestureDetector>
);
}
スクショやメディアアクセスのライブラリのインストール
npx expo install react-native-view-shot expo-media-library
この記事が気に入ったらサポートをしてみませんか?