React Native Plant App UI #4 : Illustration Slider and Animated Steps

This tutorial is the fourth part of our React Native Plant App tutorial series. In the previous part, we successfully implemented as well as sectioned out some of the UI sections of the Welcome screen. This tutorial is the continuation of the same tutorial from where we left off in the last part. So, it is recommended to go through the previous part in order to get insight and knowledge of the overall project.

In case of wanting to learn from the beginning, all the previous parts for this tutorial series are available below:

As stated in the previous parts, the motivation to work on this tutorial series came from React Native App Templates that provide a wide variety of mobile application templates written in React Native and powered by universal features and design. These app templates allow us to implement our own apps and even start our own startups. And, this fourth part is also the continuation of coding implementations and designs from the Youtube video tutorial by React UI Kit for the Plant App. The video tutorial seems to deliver the coding implementation of the overall app very thoroughly. However, there is no verbal guidance for coding and implementation. This tutorial series is the implementation of the same coding style and designs in the form of the article. Thus, the learners can go through each step and take their time understanding the implementations.

Overview

In this fourth part of this tutorial series, we are going to implement the UI sections that we separated out in our last tutorial part. The UI sections that we separated were Illustration section and Steps(Delimiter Dots) section. The idea is to start by implementing the Illustration section with a horizontal image slider on the Welcome screen. Then, we are going to add the Delimiter Dots known as Steps section below the Image Illustrations. Then, we will set animation for the active Delimiter dots as per the sliding of Illustration images.

So, let us begin!!

Importing Images as Props

Here, we are going to import the images for the illustration slider section. We are going to import the illustrations as props using defaultProps module. In order to do this, we need to use the code from the following code snippet:

Welcome.defaultProps = {
  illustrations: [
    { id: 1, source: require('../assets/images/illustration_1.png') },
    { id: 2, source: require('../assets/images/illustration_2.png') },
    { id: 3, source: require('../assets/images/illustration_3.png') },
  ],
};

Here, we have defined an array called illustrations which holds objects with image id and image source. Now, we can use the illustrations variable as a prop in our Welcome screen.

Implementing Illustrations Section

Now, we are going to implement for illustration section that we sectioned out in our previous tutorial in the form of the function called renderIllustrations(). In this illustration section, we are going to display the images as a horizontal slider. For that, we need to use the code from the following code snippet:

state = {
  }
renderIllustrations(){
    const { illustrations } = this.props;

Here, we have initialized the state variable. Also, we have defined the illustrations constant from props. Now, we are going to display the images in the illustration section as a horizontal slider.

Using FlatList component

Here, we are going to use the FlatList component in order to render the images. Then, we are going to configure the FlatList with different prop configurations in order to display the horizontal image slider properly. For that, we need to use the code from the following code snippet in the renderIllustrations() function:

<FlatList
  horizontal
  pagingEnabled
  scrollEnabled
  showsHorizontalScrollIndicator={false}
  scrollEventThrottle={16}
  snapToAlignment="center"
  data={illustrations}
  extraDate={this.state}
  keyExtractor={(item, index) => `${item.id}`}
  renderItem={({ item }) => (
    <Image
      source={item.source}
      resizeMode="contain"
    />
  )}
/>

Here, we have a FlatList with different prop configurations which are explained below:

  • pagingEnabled: When its value is true, the scroll view stops on multiples of the scroll view’s size when scrolling. The default value is false.
  • scrollEnabled: When its value is false, the view cannot be scrolled via touch interaction. The default value is true.
  • showsHorizontalScrollIndicator: When its value is false, the horizontal scroll bar at the bottom does not show up.
  • scrollEventThrottle: This prop is used to controls how often the scroll event will be fired while scrolling (as a time interval in ms). A lower number corresponds to better accuracy for code that is tracking the scroll position.
  • snapToAlignment: This prop will define the relationship of the snapping to the scroll view.

Here, we also have the keyExtractor prop which is used to identify each item in the list uniquely. Then, we have the renderItem prop which enables us to return the template of each item in the list. In this case, it returns the Image component that has its source from the illustrations array.

Hence, we will get the following result in our emulator screen:

As we can see, we have got the illustration section with a horizontal image slider. But, the images and sliding action does not seem appealing. Hence, we are going to use some styling properties to our FlatList and its Image component.

Configuring Illustration styles

Here, we are going to configure some styles to the FlatList and its Image component. For that, we are going to use the Dimensions component from the react-native package. This Dimensions component allows us to get the full height and width of the app screen so that we can configure the styles using these size variables. For that, we need to import the Dimensions component first as shown in the code snippet below:

import { StyleSheet, FlatList, Image, Dimensions } from 'react-native';

Now, we need to use the get() function provided by the Dimensions component as shown in the code snippet below:

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

Now, we are going to use these width and height constants to style our illustrations in the renderIllustrations() function:

<FlatList
   horizontal
   pagingEnabled
   scrollEnabled
   showsHorizontalScrollIndicator={false}
   scrollEventThrottle={16}
   snapToAlignment="center"
   data={illustrations}
   extraDate={this.state}
   keyExtractor={(item, index) => `${item.id}`}
   renderItem={({ item }) => (
     <Image
       source={item.source}
       resizeMode="contain"
       style={{ width, height: height / 2, overflow: 'visible' }}
     />
   )}
 />

Hence, we will get the following result in our emulator screen:

As we can see, we have got the Illustrations section with a proper image slider now. And, the sliding action looks smooth and appealing.

Implementing Steps Section

In this step, we are going to implement the Steps section which will include the delimiter dots as per the number of Illustration section images. Since there are three images, there will be three delimiter dots. We have section out this section as renderSteps() function in our last tutorial part. Now, we are going to add the Delimiter dots to this function. For that, we need to use the code from the following code snippet:

renderSteps(){
   const { illustrations } = this.props
   return(
     <Block row center middle style={styles.stepsContainer}>
       {illustrations.map((item, index) => {
         return (
           <Block
             animated
             flex={false}
             key={`step-${index}`}
             color="gray"
             style={[styles.steps]}
           />
         )
       })}
     </Block>
   )
 }

Here, in the renderSteps() function, we have defined the illustrations constant from props as in the renderIllustration() function. Then, we have returned the template with a parent component as Block with some style props. The Block template wraps the template for the delimiter dots. Here in order to make the number of delimiter dots equal to the number of illustration images, we have used the map() array function in the illustrations array. The map() function iterates through each of the items in the illustrations array and returns the template for each item. In this case, we have used the map() function only to make the number of delimiter dots equal to illustration images number. Then, inside the map() function, we have returned the Block component with props and styles.

The required styles are provided in the code snippet below:

const styles = StyleSheet.create({
  stepsContainer: {
    position: 'absolute',
    bottom: theme.sizes.base * 3,
    right: 0,
    left: 0,
  },
  steps: {
    width: 5,
    height: 5,
    borderRadius: 5,
    marginHorizontal: 2.5,
  },
});

Hence, we will get the following result in our emulator screen:

As we can see, we have got the Delimiter dots at the bottom of the Illustration images. As of now, these dots will just appear lifeless as style. But we are going to add the active style with animation to these dots on the basis of the sliding of images.

Adding Active Style Animation

Here, we are going to add the Animation to our Delimiter Dots in our Steps section. For that, we need to import the Animated component from the react-native package as shown in the code snippet below:

import { StyleSheet, FlatList, Image, Dimensions, Animated } from 'react-native';

Now, we need to define a variable called scrollX that is initialized to Animated value. This variable will store our animation value for horizontal animation. In order to do this, we need to use the code from the following code snippet:

export default class Welcome extends React.Component {
  
  scrollX = new Animated.Value(0);
  state = {
  }
.......................

Here, the Animated.Value configuration enables us to bind to style properties or other props and can be interpolated as well.

Now, we need to configure this scrollX value into the onScroll event of the FlatList component of renderIllustrations() function as shown in the code snippet below:

<FlatList
   horizontal
   pagingEnabled
   scrollEnabled
   showsHorizontalScrollIndicator={false}
   scrollEventThrottle={16}
   snapToAlignment="center"
   data={illustrations}
   extraDate={this.state}
   keyExtractor={(item, index) => `${item.id}`}
   renderItem={({ item }) => (
     <Image
       source={item.source}
       resizeMode="contain"
       style={{ width, height: height / 2, overflow: 'visible' }}
     />
   )}
   onScroll={
     Animated.event([{
       nativeEvent: { contentOffset: { x: this.scrollX } }
     }])
   }
 />

Here, we have used the event function of the Animated component which takes the nativeEvent as a parameter. Then, we have defined the contentOffset value according to the scrollX variable inside the nativeEvent config.

Configuring Animation in Delimiter dots

Here, we are going to add animation to the Delimiter dots which will depend on the onScroll event of the FlatList component of renderIllustrations() function. For that, we need to first initialize the step position using the divide function of the Animated component. The divide function creates a new Animated value composed by dividing the first Animated value by the second Animated value. And, its use is shown in the code snippet below:

const stepPosition = Animated.divide(this.scrollX, width);

Now, we are going to make some configuration in the renderSteps() function in order to add animation properties to the Delimiter dots. For that, we need to use the code from the code snippet below in the renderSteps() function:

<Block row center middle style={styles.stepsContainer}>
   {illustrations.map((item, index) => {
     const opacity = stepPosition.interpolate({
       inputRange: [index - 1, index, index + 1],
       outputRange: [0.4, 1, 0.4],
       extrapolate: 'clamp',
     });
     return (
       <Block
         animated
         flex={false}
         key={`step-${index}`}
         color="gray"
         style={[styles.steps, { opacity }]}
       />
     )
   })}
 </Block>

Here, we have defined a constant called opacity which is initialized to the interpolate() function of the stepPosition constant initlized to Animated.divide. The interpolate() function takes inputRange, outputRange and extrapolate as parameter values. The interpolate() function permits input ranges to map to different output ranges. Then, we have added opacity constant to the style prop of the Block component.

Hence, we will get the following result in our emulator screen:

As we can see, we have got the active style animation in the Delimiter dots of the Steps section when sliding the images of the Illustrations section. On top of that, the animation looks pretty smooth and appealing. With this, we have come to the end of this part of our tutorial.

Finally, we have successfully implemented the Illustratrations section with the image slider and Steps section with animated Delimiter dots in our Welcome screen of Plant App UI.

Conclusion

This tutorial is the fourth part of the React Native Plant App UI tutorial series. In this part, we continued from where we left off in the third part of this tutorial series. In this part of the tutorial, we got stepwise guidance on how to add an image slider using the FlatList component into our Illustrations section. We also learned how to add a beautiful active style animation to the Delimiter dots of the Steps section. Hence, we made the active animation of Delimeter dots in accordance with the sliding of images in the Illustrations section.

In the next part of this tutorial series, we are going to implement the Terms of Service section using a Modal view on our Welcome screen.