This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
使用图片选择器
编辑页面
在本教程中,了解如何使用 Expo Image Picker。
React Native 提供了内置组件,作为标准构建块,例如 <View>、<Text> 和 <Pressable>。我们正在构建一个功能,用于从设备的媒体库中选择图片。仅靠核心组件无法实现这一点,因此我们需要一个库来为应用添加这个功能。
我们将使用 expo-image-picker,这是 Expo SDK 中的一个库。
expo-image-picker提供对系统 UI 的访问,用于从手机的图库中选择图片和视频。

了解如何使用 expo-image-picker 从设备的媒体库中选择图片。
1
安装 expo-image-picker
要安装 expo-image-picker 库,请先在终端中按 Ctrl + C 停止开发服务器,然后运行以下命令:
- npx expo install expo-image-pickernpx expo install 命令会安装该库,并将其添加到项目的 package.json 依赖中。
提示: 每当我们在项目中安装新库时,都先在终端中按 Ctrl + C 停止开发服务器,然后运行安装命令。安装完成后,再运行npx expo start重新启动开发服务器。
2
从设备的媒体库中选择图片
expo-image-picker 提供 launchImageLibraryAsync() 方法,通过从设备的媒体库中选择图片或视频来显示系统 UI。我们将使用上一章创建的主主题按钮,从设备的媒体库中选择图片,并创建一个函数来打开设备的图片库以实现此功能。
在 app/(tabs)/index.tsx 中,导入 expo-image-picker 库,并在 Index 组件内部创建一个 pickImageAsync() 函数:
// ...其余导入语句保持不变 import * as ImagePicker from 'expo-image-picker'; export default function Index() { const pickImageAsync = async () => { let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], allowsEditing: true, quality: 1, }); if (!result.canceled) { console.log(result); } else { alert('You did not select any image.'); } }; // ...其余代码保持不变 }
让我们来了解一下上面的代码做了什么:
launchImageLibraryAsync()接收一个对象,用于指定不同的选项。这个对象是ImagePickerOptions对象,我们在调用该方法时会传入它。- 当
allowsEditing设置为true时,用户可以在 Android 和 iOS 上的选择过程中裁剪图片。
3
更新按钮组件
按下主按钮时,我们会在 Button 组件上调用 pickImageAsync() 函数。更新 components/Button.tsx 中 Button 组件的 onPress 属性:
import { StyleSheet, View, Pressable, Text } from 'react-native'; import FontAwesome from '@expo/vector-icons/FontAwesome'; type Props = { label: string; theme?: 'primary'; onPress?: () => void; }; export default function Button({ label, theme, onPress }: Props) { if (theme === 'primary') { return ( <View style={[ styles.buttonContainer, { borderWidth: 4, borderColor: '#ffd33d', borderRadius: 18 }, ]}> <Pressable style={[styles.button, { backgroundColor: '#fff' }]} onPress={onPress}> <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, }, });
在 app/(tabs)/index.tsx 中,将 pickImageAsync() 函数添加到第一个 <Button> 的 onPress 属性中。
import { View, StyleSheet } from 'react-native'; import * as ImagePicker from 'expo-image-picker'; import Button from '@/components/Button'; import ImageViewer from '@/components/ImageViewer'; const PlaceholderImage = require('@/assets/images/background-image.png'); export default function Index() { const pickImageAsync = async () => { let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], allowsEditing: true, quality: 1, }); if (!result.canceled) { console.log(result); } else { alert('You did not select any image.'); } }; return ( <View style={styles.container}> <View style={styles.imageContainer}> <ImageViewer imgSource={PlaceholderImage} /> </View> <View style={styles.footerContainer}> <Button theme="primary" label="Choose a photo" onPress={pickImageAsync} /> <Button label="Use this photo" /> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#25292e', alignItems: 'center', }, imageContainer: { flex: 1, }, footerContainer: { flex: 1 / 3, alignItems: 'center', }, });
pickImageAsync() 函数调用 ImagePicker.launchImageLibraryAsync(),然后处理返回结果。launchImageLibraryAsync() 方法会返回一个包含所选图片信息的对象。
下面是 result 对象的示例以及它包含的属性:
{ "assets": [ { "assetId": null, "base64": null, "duration": null, "exif": null, "fileName": "ea574eaa-f332-44a7-85b7-99704c22b402.jpeg", "fileSize": 4513577, "height": 4570, "mimeType": "image/jpeg", "rotation": null, "type": "image", "uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252FStickerSmash-13f21121-fc9d-4ec6-bf89-bf7d6165eb69/ImagePicker/ea574eaa-f332-44a7-85b7-99704c22b402.jpeg", "width": 2854 } ], "canceled": false }
{ "assets": [ { "assetId": "99D53A1F-FEEF-40E1-8BB3-7DD55A43C8B7/L0/001", "base64": null, "duration": null, "exif": null, "fileName": "IMG_0004.JPG", "fileSize": 2548364, "height": 1669, "mimeType": "image/jpeg", "type": "image", "uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252FStickerSmash-13f21121-fc9d-4ec6-bf89-bf7d6165eb69/ImagePicker/ea574eaa-f332-44a7-85b7-99704c22b402.jpeg", "width": 1668 } ], "canceled": false }
{ "assets": [ { "fileName": "some-image.png", "height": 720, "mimeType": "image/png", "uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABQAA" } ], "canceled": false }
4
使用所选图片
result 对象提供了 assets 数组,其中包含所选图片的 uri。让我们从图片选择器中取出这个值,并将其用于在应用中显示所选图片。
修改 app/(tabs)/index.tsx 文件:
- 使用 React 的
useState钩子声明一个名为selectedImage的状态变量。我们将使用这个状态变量来保存所选图片的 URI。 - 更新
pickImageAsync()函数,将图片 URI 保存到selectedImage状态变量中。 - 将
selectedImage作为 prop 传递给ImageViewer组件。
import { View, StyleSheet } from 'react-native'; import * as ImagePicker from 'expo-image-picker'; import { useState } from 'react'; import Button from '@/components/Button'; import ImageViewer from '@/components/ImageViewer'; const PlaceholderImage = require('@/assets/images/background-image.png'); export default function Index() { const [selectedImage, setSelectedImage] = useState<string | undefined>(undefined); const pickImageAsync = async () => { let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], 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 imgSource={PlaceholderImage} selectedImage={selectedImage} /> </View> <View style={styles.footerContainer}> <Button theme="primary" label="Choose a photo" onPress={pickImageAsync} /> <Button label="Use this photo" /> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#25292e', alignItems: 'center', }, imageContainer: { flex: 1, }, footerContainer: { flex: 1 / 3, alignItems: 'center', }, });
将 selectedImage prop 传递给 ImageViewer 组件,以显示所选图片而不是占位图片。
- 修改 components/ImageViewer.tsx 文件,以接收
selectedImageprop。 - 图片的源代码现在变得很长,所以我们也把它移动到一个单独的变量
imageSource中。 - 将
imageSource作为Image组件上sourceprop 的值传入。
import { ImageSourcePropType, StyleSheet } from 'react-native'; import { Image } from 'expo-image'; type Props = { imgSource: ImageSourcePropType; selectedImage?: string; }; export default function ImageViewer({ imgSource, selectedImage }: Props) { const imageSource = selectedImage ? { uri: selectedImage } : imgSource; return <Image source={imageSource} style={styles.image} />; } const styles = StyleSheet.create({ image: { width: 320, height: 440, borderRadius: 18, }, });
在上面的代码片段中,Image 组件使用条件运算符来加载图片源。所选图片是一个 uri 字符串,而不是像占位图片那样的本地资源。
让我们看看现在的应用:
本教程中示例应用使用的图片来自 Unsplash。
摘要
Chapter 4: Use an image picker
We've successfully added the functionality to pick an image from the device's media library.
In the next chapter, we'll learn how to create an emoji picker modal component.