An Image/Video Gallery is a common feature in mobile applications. This article will guide you for creating an Image/Video Gallery using React Native.We will learn to build an Image/Video Gallery app using React-Native. In this app, we will display the images and videos in the form of a grid, and on clicking, we can view them. If an image is clicked, the image viewer is opened, similarly, if a video is clicked, a video player is launched. By the end of this tutorial, you will have solid understanding of MediaLibrary usage in React Native.
Preview of final output: Let us have a look at how the final output will look like
Prerequisites and Technolgies Used
- Introduction to React Native
- Introduction React Native Components
- React Native State
- React Native Props
- Expo CLI
- Node JS and npm (Node Package Manager)
Approach to create Image/Video Gallery App
- The application will be single page app.
- It will contain two types, image and video so we used useState hook with default value of image.
- Using the FlatList component, we load the assets from MediaLibrary. It gets the permission from user in the device.
- On getting the assets, we display the image and videos in different tabs using Buttons.
- We wrap the images with Pressable. On clicking, we set the file location .
- The Modal component becomes visible on setting the imageName variable. Here we check if image, we display an image, else video.
Steps to create the project:
Step 1: Create the project:
npx create-expo-app image-video-gallery-app
Step 2: Navigate to the project
cd image-video-gallery-app
Step 3: Install the required libraries
npx expo install expo-av
npx expo install expo-image
npx expo install expo-media-library
Step 4: Configuration in app.json/app.config.js
{
"expo": {
"plugins": [
[
"expo-media-library",
{
"photosPermission": "Allow $(name) to access your photos.",
"savePhotosPermission": "Allow $(name) to save photos.",
"videosPermission": "Allow $(name) to access your videos.",
"isAccessMediaLocationEnabled": true
}
]
]
}
}
Project Structure:
The updated dependencies in package.json file will look like:
"dependencies": {
"expo": "~49.0.15",
"expo-status-bar": "~1.6.0",
"react": "18.2.0",
"react-native": "0.72.6",
"expo-media-library": "~15.4.1",
"expo-image": "~1.3.5",
"expo-av": "~13.4.1"
},
"devDependencies": {
"@babel/core": "^7.20.0"
}
Example: In this example we are following the above-explained approach.
// App.js import { StatusBar } from "expo-status-bar" ;
import { Button,
FlatList,
Modal,
Pressable,
ScrollView,
StyleSheet,
Text,
View,
} from "react-native" ;
import * as MediaLibrary from "expo-media-library" ;
import { useState } from "react" ;
import { Image } from "expo-image" ;
import { Video, ResizeMode } from "expo-av" ;
export default function App() {
const [galleryFiles, setGalleryFiles] = useState([]);
const [currentImage, setCurrentImage] = useState( "" );
const [mediaType, setMediaType] = useState( "image" );
const fetchMedia = async (first, mediaType) => {
const { status } = await MediaLibrary.requestPermissionsAsync();
if (status === "granted" ) {
const media = await MediaLibrary.getAssetsAsync({
first: first + 30,
sortBy: MediaLibrary.SortBy.creationTime,
mediaType:
mediaType === "image"
? MediaLibrary.MediaType.photo
: MediaLibrary.MediaType.video,
});
setGalleryFiles(media.assets);
}
};
const renderItem = ({ item }) => (
<View style={styles.imageContainer}>
<Pressable
onPress={() => {
setCurrentImage(item.uri);
setMediaType(item.mediaType);
}}
>
<Image
source={{ uri: item.uri }}
style={{ width: 200, height: 200 }}
/>
</Pressable>
</View>
);
return (
<View style={styles.container}>
<StatusBar style= "auto" />
<Text style={styles.heading}>Welcome to GeeksforGeeks</Text>
<View
style={{
flexDirection: "row" ,
justifyContent: "space-around" ,
width: "100%" ,
padding: 10,
}}
>
<Button
title= "Images"
onPress={() => {
setMediaType( "image" );
fetchMedia(0, "image" );
}}
/>
<Button
title= "Videos"
onPress={() => {
setMediaType( "video" );
fetchMedia(0, "video" );
}}
/>
</View>
{ /* view full image in modal */ }
<Modal visible={currentImage !== "" } transparent={ false }>
<View style={{ flex: 1, backgroundColor: 0 }}>
<Pressable
style={{
position: "absolute" ,
top: 40,
zIndex: 1,
flex: 1,
alignSelf: "center" ,
}}
title= "Close"
onPress={() => setCurrentImage( "" )}
>
<Text
style={{
color: "black" ,
fontSize: 20,
padding: 10,
backgroundColor: "white" ,
}}
>
Close
</Text>
</Pressable>
{mediaType === "video" ? (
<Video
style={{
width: "100%" ,
height: "100%" ,
}}
source={{
uri: currentImage,
}}
useNativeControls
resizeMode={ResizeMode.CONTAIN}
isLooping
/>
) : (
<Image
source={{ uri: currentImage }}
style={{ width: "100%" , height: "100%" }}
/>
)}
</View>
</Modal>
<View style={styles.scrollContainer}>
<Text style={{ fontSize: 20, marginBottom: 20 }}>
My Gallery
</Text>
<FlatList
data={galleryFiles}
renderItem={renderItem}
keyExtractor={(item) => item.id}
numColumns={3}
onEndReached={() => {
fetchMedia(galleryFiles.length, mediaType);
}}
onLayout={() => {
fetchMedia(galleryFiles.length, mediaType);
}}
/>
</View>
</View>
);
} const styles = StyleSheet.create({ container: {
flex: 1,
justifyContent: "center" ,
alignItems: "center" ,
marginTop: "10%" ,
},
scrollContainer: {
flex: 1,
marginTop: 20,
width: "100%" ,
},
heading: {
color: "green" ,
fontSize: 30,
textAlign: "center" ,
fontWeight: "bold" ,
},
imageContainer: {
flex: 1,
margin: 1,
aspectRatio: 1, // This ensures that images maintain their aspect ratio
borderRadius: 8,
overflow: "hidden" ,
},
image: {},
}); |
Steps to run the application:
Step 1: Navigate to the terminal or command prompt and type the required command there to run the React native application.
npx expo start
Step 2: Depending on your operating system, type the following command in terminal
- To run on Android:
npx react-native run-android
- To run on Ios:
npx react-native run-ios
Step optional: To run on Web, you need to install the following packages
npx expo install react-dom react-native-web @expo/webpack-config
Step 3: To run on web, press w on Terminal will application is running. For Android/IOS, install the Expo app and scan the QR code or enter the link of Metro in the Terminal.
Output: