Carousel in React Native

Image Carousel also popularly known as Slider components are one of the most appealing parts of the mobile applications and is used extensively. We can get it through various libraries that provide the slider functionality but today we will be focusing on the custom slider. 

We can achieve it using ScrollView but Here we will learn how to make an image slider with our basic FlatList component.

Reason for selecting FlatList:

  1. It has inbuilt functionality for a horizontal list.
  1. It has inbuilt gesture handling and saves our gesture handling implementation.
  1. It provides loading & rendering optimization of child views.

Let’s start with the coding. Here we will be splitting our code into the component. Let’s create our First Main component i.e Home and import images as array (in JSON format).

import React from 'react'

import {View, Text} from 'react-native'

import Carousel from '../component/Carousel'

import { dummyData } from '../data/Data' 


const Home = ({navigation}) =>{

    return (

        <View>

            <Carousel data = {dummyData}/>

        </View>

    )

}

export default Home;

The second component which we will be creating is the Carousel Component.

Carousel component accepts data as props from Home Component ( which basically contains data in JSON format ). In today’s discussion, we are storing data locally but in real-time we get data as a result of some request which may take the time or may get some faulty data. 

So we will be adding condition which will first check for valid data and if it present then only render to the screen else will show popup to add images. We also want our scrolling to be horizontal and doesn’t want to have a scroll bar. Therefore adding horizontal property and showsHorizontalScrollIndicator to false. Also, we want to have scrolling property fast and smooth. So applying decelerationRate to fast and scrollEventThrottle property to some higher (value say 16 ).

Now we are left with one last thing i.e carousel dots. We will be handling this using onScroll prop of FlatList which automatically triggered on scrolling list rendered using FlatList.

Complete code of the implementation is shown below.

import React, { useState, useEffect } from 'react'

import { View, Text, StyleSheet, Dimensions, FlatList, Animated } from 'react-native'

import CarouselItem from './CarouselItem'

const Carousel = ({ data }) => {

    const scrollX = new Animated.Value(0)

    let position = Animated.divide(scrollX, width)

    const [dataList, setDataList] = useState(data)    

    if (data && data.length) {

        return (

            <View>

                <FlatList data={data}

                ref = {(flatList) => {this.flatList = flatList}}

                    keyExtractor={(item, index) => 'key' + index}

                    horizontal

                    pagingEnabled

                    scrollEnabled

                    snapToAlignment="center"

                    scrollEventThrottle={16}

                    decelerationRate={"fast"}

                    showsHorizontalScrollIndicator={false}

                    renderItem={({ item }) => {

                        return <CarouselItem item={item} />

                    }}

                    onScroll={Animated.event(

                        [{ nativeEvent: { contentOffset: { x: scrollX } } }]

                    )}

                />

                <View style={styles.dotView}>

                    {data.map((_, i) => {

                        let opacity = position.interpolate({

                            inputRange: [i - 1, i, i + 1],

                            outputRange: [0.3, 1, 0.3],

                            extrapolate: 'clamp'

                        })

                        return (

                            <Animated.View

                                key={i}

                                style={{ opacity, height: 10, width: 10, backgroundColor: '#595959', margin: 8, borderRadius: 5 }}

                            />

                        )

                    })}

                </View>

            </View>

        )

    }    

    return Alert.alert('Please provide Images')

}

const styles = StyleSheet.create({

    dotView: { flexDirection: 'row', justifyContent: 'center' }

})

export default Carousel;

Third and the last Component we will be creating is CarouselItem component which holds individual property of each image from whole JSON data. Using Dimensions get the method we will find the dimensions of different devices. So that we can achieve responsive design by setting the width and height of the image as per different mobile devices. We will be setting the height of the image to 1/3 of the device screen and width 15px less than the width of the device to achieve some spacing between each image.

In this component, we will be dealing with each individual property of image Array.  Here item is a prop which has a property such as an image path title and description.

Complete implementation of code is shown below.

import React from 'react'

import { View, StyleSheet, Text, Image, Dimensions } from 'react-native' 

const { width, height } = Dimensions.get('window')


const CarouselItem = ({ item }) => {

    return (

        <View style={styles.cardView}>

            <Image style={styles.image} source={{ uri: item.url }} />

            <View style={styles.textView}>

                <Text style={styles.itemTitle}> {item.title}</Text>

                <Text style={styles.itemDescription}>{item.description}</Text>

            </View>

        </View>

    )

} 

const styles = StyleSheet.create({

    cardView: {

        flex: 1,

        width: width - 15,

        height: height / 3,

        backgroundColor: 'white',

        margin: 10,

        borderRadius: 10,

        shadowColor: '#000',

        shadowOffset: { width: 0.5, height: 0.5 },

        shadowOpacity: 0.5,

        shadowRadius: 3,

        elevation: 5,

    }, 

    textView: {

        position: 'absolute',

        bottom: 10,

        margin: 10,

        left: 5,

    },

    image: {

        width: width - 20,

        height: height / 3,

        borderRadius: 10

    },

    itemTitle: {

        color: 'white',

        fontSize: 22,

        shadowColor: '#000',

        shadowOffset: { width: 0.8, height: 0.8 },

        shadowOpacity: 1,

        shadowRadius: 3,

        marginBottom: 5,

        fontWeight: "bold",

        elevation: 5

    },

    itemDescription: {

        color: 'white',

        fontSize: 12,

        shadowColor: '#000',

        shadowOffset: { width: 0.8, height: 0.8 },

        shadowOpacity: 1,

        shadowRadius: 3,

        elevation: 5

    }

}) 

export default CarouselItem

 

Leave a Reply