Search code examples
react-nativelottiereact-navigation-bottom-tab

How to play a Lottie animation only once in LottieView?


I have developed a bottom tab navigator and used Lottie animations as icons. I want them to autoplay and get played only once when it's in focus (like the Binance app). I have tried with loop={false} but that stops it from animating altogether. The code is as follow:

import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import LottieView from 'lottie-react-native';

import Home from './Home';
import Create from './Create';
import Messages from './Messages';
import Forum from './Forum';
import Profile from './Profile';

const Tab = createBottomTabNavigator();

export default function Tabs() {
  return (
    <Tab.Navigator
      screenOptions={({ route }) => ({
        tabBarIcon: ({ focused, color, size }) => {
          let filePath;

          switch (route.name) {
            case 'Home':
              filePath = require('../tabanimations/hometab.json');
              break;
            case 'Messages':
              filePath = require('../tabanimations/messagestab.json');
              break;
            case 'Create':
              filePath = require('../tabanimations/hometab.json');
              break;
            case 'Forum':
              filePath = require('../tabanimations/forumtab.json');
            case 'Profile':
              filePath = require('../tabanimations/profiletab.json');

              break;
          }

          return <LottieView source={filePath} autoPlay={focused} />;
        },
      })}>
      <Tab.Screen name="Home" component={Home} />
      <Tab.Screen name="Messages" component={Messages} />
      <Tab.Screen name="Create" component={Create} />
      <Tab.Screen name="Forum" component={Forum} />
      <Tab.Screen name="Profile" component={Profile} />
    </Tab.Navigator>
  );
}

How to play the animation only once on focus?


Solution

  • Use loop={false} and autoPlay={false} then use play() to run on focus
    your code may be lookalike this

    tabBarIcon: ({ focused, color, size }) => {
        return <CustomTab focused={focused} color={color} size={size} route={route}/>
    }
    
    
    const CustomTab = ({ focused, color, size, route}) => {
    
        const ref = React.useRef();
        let filePath;
    
        //on focus change the anim will play
        React.useEffect(() => {
            if(focused && ref.current){
                ref.current?.play();
            }
        }, [focused, ref.current]);
    
        switch (route.name) {
            case 'Home':
                filePath = require('../tabanimations/hometab.json');
                break;
            case 'Messages':
                filePath = require('../tabanimations/messagestab.json');
                break;
            case 'Create':
                filePath = require('../tabanimations/hometab.json');
                break;
            case 'Forum':
                filePath = require('../tabanimations/forumtab.json');
            case 'Profile':
                filePath = require('../tabanimations/profiletab.json');
    
                break;
        }
    
        return (
            <LottieView 
                ref={ref}
                loop={false}
                source={filePath} 
                autoPlay={false} />
        );
    };
    

    you can also use play like this ref.current?.play(0, 1) to ensure it always start from 0 you can see LottieView Methods here