如何实现Flutter中的Lottie动画

3,676 阅读6分钟

Flutter中的Lottie动画

动画是每个移动应用程序的基础。它们使应用程序的用户界面具有吸引力和使用乐趣。然而,动画的实现可能具有挑战性。Lottie动画的出现,让实施变得更加容易。

Lottie是一个基于JSON的动画文件。它们可以作为静态和网络资产使用。此外,它们还可以擦亮你的应用程序的用户界面,使其对用户具有直观性。

在这篇文章中,我们将在一个Flutter应用程序中实现Lottie动画。Flutter中的动画控制器给了我们对动画的高级控制。因此,我们将使用一个动画控制器来控制我们的Flutter应用程序中的Lottie动画的状态。

前提条件

  1. 对[Dart]编程语言有扎实的了解。
  2. 对[Flutter小部件]有扎实的了解。
  3. 在Flutter中使用[动画控制器]的基本知识。

本教程假定您的计算机上已经安装了Flutter。

我们将使用Flutter 2.5.3版本来构建我们的项目。

我们将使用安装了Flutter插件的Android Studio作为我们的IDE。也可以使用Visual Studio Code

第一步:将Lottie依赖性添加到项目中

进入IDE中的集成终端,执行这个命令。

flutter pub add Lottie

你会看到在项目的pubspec.yaml 文件中添加了下面这样一行。

dependencies:
  Lottie: ^1.2.1 //Lottie Animation Library

一旦Lottie依赖性被添加到项目中,你就可以通过在main.dart 文件中添加这行来将其导入到dart代码中。

import 'package:lottie/lottie.dart';

第二步:将资产添加到项目中

首先,访问Lottie动画以获得Lottie动画JSON文件,然后选择并下载你所选择的动画。

接下来,在你的项目目录下创建一个assets 文件夹,并在那里添加Lottie文件。

最后,在项目中的pubspec.yaml 文件中添加你的资产文件夹,如下图所示,然后运行flutter pub get

assets:
 - assets/

第三步:创建LottieScreen页面

main.dart ,创建一个新的有状态的widget类,名为LottieScreen,它将返回一个Scaffold,包含一个带有标题的应用程序栏;Lottie implementation 。如下图所示。

class LottieScreen extends StatefulWidget {
  const LottieScreen({Key? key}) : super(key: key);

  @override
  _LottieScreenState createState() => _LottieScreenState();
}

class _LottieScreenState extends State<LottieScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Lottie Implementation"),
        centerTitle: true,
      ),
    );
  }
}

接下来,在Scaffold中添加一个body 。该主体将包含以下小部件。

  • 中心部件 - 将子部件在屏幕上居中。
  • Column widget,它将包括Center widget的一个子项,将子项垂直排列。

第四步:使用Lottie动画

1.网络Lottie

要添加一个网络Lottie动画,去Lottie文件网站,复制你选择的Lottie的URL。

添加一个Lottie.network('') widget作为Column widget中的一个子项。粘贴Lottie URL,如下图所示。

body: Center(
    child: Lottie.network("https://assets8.lottiefiles.com/packages/lf20_xxjvkrex.json",
    animate: true
    ),
),

当应用程序被运行时,动画会自动播放。这种自动播放可以通过在Lottie小组件内部添加animate: false 属性来改变。之后,Lottie动画就变成了一个静态的图像。

2.资产Lottie

Lottie.asset('') 方法显示Lottie JSON文件,这些文件存储在本地的assets文件夹中,如下图所示。

body: Center(
  child: Lottie.asset("assets/transaction-completed.json"),
),

第五步:动画控制器

为了全面解释Flutter中动画控制器的使用,我们将使用上面添加到我们项目中的Lottie资产动画实现一个动画控制器。

我们将创建一个按钮,当按下时,会出现一个包含Lottie资产的对话框,通知用户命令已经成功执行。

这是该按钮的代码。

body: Center(
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Lottie.network("https://assets8.lottiefiles.com/packages/lf20_xxjvkrex.json", animate: true),
        const SizedBox(height: 24,),
        ElevatedButton(
            onPressed: () => showSuccessfulDialog(),
            child: const Text("Update Transactions"),
            )
    ],),
),

当按钮被按下时,showSuccessfulDialog() 方法被执行。这个方法是显示对话框的方法。这是showSuccessfulDialog() 方法的代码。

void showSuccessfulDialog() => showDialog(
      context: context,
      builder: (context) => Dialog(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Lottie.asset("assets/transaction-complete.json",
                repeat: false,
              controller: lottieController,
              onLoaded: (composition) {
              controller.duration = composition.duration;
              controller.forward();
              }
            ),
            const SizedBox(height: 8),
            const Center(
              child: Text("Done!", style: TextStyle(
                  color: Colors.green,
                  fontSize: 21),),
            ),
            const SizedBox(height: 14),
          ]
        ),
      )
  );

从上面的代码中,我们已经创建了一个对话框,当按钮被点击时就会出现,在Lottie动画完成后就会消失。

我们在Lottie上设置了repeat: false 属性,使动画只播放一次而不是循环播放。我们将在我们的状态中创建一个新的动画控制器,名为lottieController ,如下图所示。

late AnimationController lottieController;

在控制器属性中,我们将把我们创建的动画控制器添加到showSuccessfulDialog() 方法中。然后,为了启动Lottie动画,我们将添加onLoaded 属性,在这里我们将用前进方法调用动画控制器。

最后,我们将使用composition.duration ,将动画的持续时间设置为Lottie文件的预设时间,如下所示。

onLoaded: (composition) {
  lottieController.forward();
  lottieController.duration = composition.duration;
}

然后我们需要创建一个initState() 方法和dispose() 方法来初始化动画,并在完成后处置它。

1. initState()方法

我们将在我们的状态中添加SingleTickerProviderStateMixin ,如图所示。

class _LottieScreenState extends State<LottieScreen> with SingleTickerProviderStateMixin{
  late AnimationController lottieController;

  @override
  void initState() {
    super.initState();

    lottieController = AnimationController(
      vsync: this,
    );

    lottieController.addStatusListener((status) async {
      if (status == AnimationStatus.completed) {
        Navigator.pop(context);
        lottieController.reset();
      }
    });
  }

我们使用SingleTickerProviderStateMixin ,因为我们的项目只使用一个动画控制器。因此,我们在initState里面调用我们的控制器,这样我们就可以通过我们的动画控制器使用用于同步我们动画帧率的vsync: this 参数。

为了在动画完成后自动关闭对话框,我们添加了一个监听动画控制器的状态监听器,如上面的代码所示。

如果动画完成了,那么对话框就会关闭。这是因为Navigator.pop(context); 代码的缘故。对话框关闭后,使用lottieController.reset(); 函数重置动画控制器,以便在我们下次点击按钮时重新播放。

接下来,创建dispose()方法,如下面的代码所示。最后,添加lottieController.dispose(); 代码,它将销毁动画控制器并将其从widget树中移除。

  @override
  void dispose() {
    lottieController.dispose();
    super.dispose();
  }

当我们的应用程序运行时,我们将得到这样的结果。

Flutter Lottie Implementation

这就是我们所创建的Flutter应用程序的完整代码。

class LottieScreen extends StatefulWidget {
  const LottieScreen({Key? key}) : super(key: key);

  @override
  _LottieScreenState createState() => _LottieScreenState();
}

class _LottieScreenState extends State<LottieScreen> with SingleTickerProviderStateMixin{
  late AnimationController lottieController;

  @override
  void initState() {
    super.initState();

    lottieController = AnimationController(
      vsync: this,
    );

    lottieController.addStatusListener((status) async {
      if (status == AnimationStatus.completed) {
        Navigator.pop(context);
        lottieController.reset();
      }
    });
  }

  @override
  void dispose() {
    lottieController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Lottie Implementation"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Lottie.asset("assets/cards.json",
            height: 300,
            width: 300,
              animate: true
            ),
            const SizedBox(height: 24,),
            ElevatedButton(
                onPressed: () => showSuccessfulDialog(),
                child: const Text("Update Transactions"),
            )
          ],
        ),

      ),
    );
  }
  void showSuccessfulDialog() => showDialog(
      context: context,
      builder: (context) => Dialog(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Lottie.asset("assets/transaction-completed.json",
                repeat: false,
                height: 200,
                width: 200,
              controller: lottieController,
              onLoaded: (composition) {
                lottieController.duration = composition.duration;
                lottieController.forward();
              }
            ),
            const Center(
              child: Text("Done!", style: TextStyle(
                  color: Colors.green,
                  fontSize: 24,
                  fontWeight: FontWeight.bold
                  ),),
            ),
            const SizedBox(height: 21),
          ]
        ),
      )
  );
}

结论

Lottie动画在Flutter应用程序中的实现非常简单和容易。我们已经在我们的应用程序中实现了这些Lottie动画。此外,我们还利用了一个动画控制器来控制我们的动画的状态。